1

I've been creating an autofill checkout pile of code for WooCommerce so that when I get people from my software to get a link to my site to purchase something. But I've been having trouble getting to work, even with incognito and a URL with dummy data in it. If someone can tell me what I'm doing wrong, or I need to put it somewhere else.

My code:

function custom_autofill_checkout_fields() {
    // Only run on checkout page
    if (!is_checkout()) {
        return;
    }

    // Get URL parameters
    $autofill_fields = array(
        'billing_first_name' => isset($_GET['fname']) ? sanitize_text_field($_GET['fname']) : '',
        'billing_last_name' => isset($_GET['lname']) ? sanitize_text_field($_GET['lname']) : '',
        'billing_email' => isset($_GET['email']) ? sanitize_email($_GET['email']) : '',
        'billing_phone' => isset($_GET['phone']) ? sanitize_text_field($_GET['phone']) : '',
        'billing_company' => isset($_GET['company']) ? sanitize_text_field($_GET['company']) : '',
        'billing_address_1' => isset($_GET['address1']) ? sanitize_text_field($_GET['address1']) : '',
        'billing_address_2' => isset($_GET['address2']) ? sanitize_text_field($_GET['address2']) : '',
        'billing_city' => isset($_GET['city']) ? sanitize_text_field($_GET['city']) : '',
        'billing_state' => isset($_GET['state']) ? sanitize_text_field($_GET['state']) : '',
        'billing_postcode' => isset($_GET['postcode']) ? sanitize_text_field($_GET['postcode']) : '',
        'billing_country' => isset($_GET['country']) ? sanitize_text_field($_GET['country']) : '',
        
        // Copy billing to shipping if requested
        'ship_to_different_address' => isset($_GET['ship_different']) && $_GET['ship_different'] === '1' ? true : false,
        
        // Shipping fields
        'shipping_first_name' => isset($_GET['ship_fname']) ? sanitize_text_field($_GET['ship_fname']) : '',
        'shipping_last_name' => isset($_GET['ship_lname']) ? sanitize_text_field($_GET['ship_lname']) : '',
        'shipping_company' => isset($_GET['ship_company']) ? sanitize_text_field($_GET['ship_company']) : '',
        'shipping_address_1' => isset($_GET['ship_address1']) ? sanitize_text_field($_GET['ship_address1']) : '',
        'shipping_address_2' => isset($_GET['ship_address2']) ? sanitize_text_field($_GET['ship_address2']) : '',
        'shipping_city' => isset($_GET['ship_city']) ? sanitize_text_field($_GET['ship_city']) : '',
        'shipping_state' => isset($_GET['ship_state']) ? sanitize_text_field($_GET['ship_state']) : '',
        'shipping_postcode' => isset($_GET['ship_postcode']) ? sanitize_text_field($_GET['ship_postcode']) : '',
        'shipping_country' => isset($_GET['ship_country']) ? sanitize_text_field($_GET['ship_country']) : '',
        
        // Order notes
        'order_comments' => isset($_GET['notes']) ? sanitize_textarea_field($_GET['notes']) : '',
    );

    // Add products to cart if product_id is provided
    if (isset($_GET['product_id'])) {
        $product_id = intval($_GET['product_id']);
        $quantity = isset($_GET['quantity']) ? intval($_GET['quantity']) : 1;
        
        // Clear cart first if requested
        if (isset($_GET['clear_cart']) && $_GET['clear_cart'] === '1') {
            WC()->cart->empty_cart();
        }
        
        // Add product to cart
        if ($product_id > 0) {
            WC()->cart->add_to_cart($product_id, $quantity);
        }
    }
    
    // Set checkout fields
    foreach ($autofill_fields as $field => $value) {
        if (!empty($value)) {
            WC()->customer->set_props(array($field => $value));
        }
    }
    
    // Add JavaScript to handle form field autofilling
    add_action('wp_footer', 'custom_autofill_checkout_javascript');
}
add_action('wp_loaded', 'custom_autofill_checkout_fields');

/**
 * Add JavaScript to ensure the checkout form fields are populated
 */
function custom_autofill_checkout_javascript() {
    if (!is_checkout()) {
        return;
    }
    
    ?>
    <script type="text/javascript">
    jQuery(document).ready(function($) {
        // Get URL parameters
        const urlParams = new URLSearchParams(window.location.search);
        
        // Map URL parameters to checkout fields
        const fieldMap = {
            'fname': '#billing_first_name',
            'lname': '#billing_last_name',
            'email': '#billing_email',
            'phone': '#billing_phone',
            'company': '#billing_company',
            'address1': '#billing_address_1',
            'address2': '#billing_address_2',
            'city': '#billing_city',
            'state': '#billing_state',
            'postcode': '#billing_postcode',
            'country': '#billing_country',
            'ship_fname': '#shipping_first_name',
            'ship_lname': '#shipping_last_name',
            'ship_company': '#shipping_company',
            'ship_address1': '#shipping_address_1',
            'ship_address2': '#shipping_address_2',
            'ship_city': '#shipping_city',
            'ship_state': '#shipping_state',
            'ship_postcode': '#shipping_postcode',
            'ship_country': '#shipping_country',
            'notes': '#order_comments'
        };
        
        // Fill form fields from URL parameters
        Object.entries(fieldMap).forEach(([param, selector]) => {
            if (urlParams.has(param)) {
                $(selector).val(urlParams.get(param)).trigger('change');
            }
        });
        
        // Handle shipping to different address
        if (urlParams.has('ship_different') && urlParams.get('ship_different') === '1') {
            $('#ship-to-different-address-checkbox').prop('checked', true).trigger('change');
        }
        
        // Ensure fields update when form refreshes
        $(document.body).on('updated_checkout', function() {
            // Re-apply values after checkout updates
            Object.entries(fieldMap).forEach(([param, selector]) => {
                if (urlParams.has(param)) {
                    $(selector).val(urlParams.get(param)).trigger('change');
                }
            });
        });
    });
    </script>
    <?php
}

/**
 * Helper function to generate an autofill checkout URL
 * 
 * @param array $customer_data Customer data to pre-fill
 * @param int|array $product_id Product ID or array of product IDs and quantities to add to cart
 * @param bool $clear_cart Whether to clear the cart before adding products
 * @return string The checkout URL with pre-fill parameters
 */
function generate_autofill_checkout_url($customer_data, $product_id = null, $clear_cart = true) {
    $checkout_url = wc_get_checkout_url();
    $params = array();
    
    // Add customer data parameters
    foreach ($customer_data as $key => $value) {
        $params[$key] = urlencode($value);
    }
    
    // Add product parameters if provided
    if ($product_id !== null) {
        $params['product_id'] = $product_id;
        $params['clear_cart'] = $clear_cart ? '1' : '0';
    }
    
    // Build URL with query string
    $checkout_url = add_query_arg($params, $checkout_url);
    
    return $checkout_url;
}
New contributor
boshuua is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
3
  • Questions: how/when are you calling this custom_prefill_checkout_fields() function exactly? And you said that you're having problems "getting it to work", what problems exactly? Commented 2 days ago
  • Hi, essentially what im trying to do is get a URL that has my customers details on it for billing. Every time i have tried a URL with dummy data in it, it doesnt enter any details. I'm not entirely sure what im getting wrong. My code will be updated on the original post.
    – boshuua
    Commented 2 days ago
  • Welcome to SO, please provide stackoverflow.com/help/minimal-reproducible-example so we can reproduce and try to help you, this is out of context. Please edit it :)
    – Marco
    Commented 2 days ago

1 Answer 1

0

You can replace wp_loaded hook with woocommerce_checkout_init action hook and for your javascript you can use wc_enqueue_js() dedicated function that includes jQuery ready event.

Try the following:

function custom_autofill_checkout_fields() {
    // Get URL parameters
    $autofill_fields = array(
        'billing_first_name' => isset($_GET['fname']) ? sanitize_text_field($_GET['fname']) : '',
        'billing_last_name' => isset($_GET['lname']) ? sanitize_text_field($_GET['lname']) : '',
        'billing_email' => isset($_GET['email']) ? sanitize_email($_GET['email']) : '',
        'billing_phone' => isset($_GET['phone']) ? sanitize_text_field($_GET['phone']) : '',
        'billing_company' => isset($_GET['company']) ? sanitize_text_field($_GET['company']) : '',
        'billing_address_1' => isset($_GET['address1']) ? sanitize_text_field($_GET['address1']) : '',
        'billing_address_2' => isset($_GET['address2']) ? sanitize_text_field($_GET['address2']) : '',
        'billing_city' => isset($_GET['city']) ? sanitize_text_field($_GET['city']) : '',
        'billing_state' => isset($_GET['state']) ? sanitize_text_field($_GET['state']) : '',
        'billing_postcode' => isset($_GET['postcode']) ? sanitize_text_field($_GET['postcode']) : '',
        'billing_country' => isset($_GET['country']) ? sanitize_text_field($_GET['country']) : '',
        
        // Copy billing to shipping if requested
        'ship_to_different_address' => isset($_GET['ship_different']) && $_GET['ship_different'] === '1' ? true : false,
        
        // Shipping fields
        'shipping_first_name' => isset($_GET['ship_fname']) ? sanitize_text_field($_GET['ship_fname']) : '',
        'shipping_last_name' => isset($_GET['ship_lname']) ? sanitize_text_field($_GET['ship_lname']) : '',
        'shipping_company' => isset($_GET['ship_company']) ? sanitize_text_field($_GET['ship_company']) : '',
        'shipping_address_1' => isset($_GET['ship_address1']) ? sanitize_text_field($_GET['ship_address1']) : '',
        'shipping_address_2' => isset($_GET['ship_address2']) ? sanitize_text_field($_GET['ship_address2']) : '',
        'shipping_city' => isset($_GET['ship_city']) ? sanitize_text_field($_GET['ship_city']) : '',
        'shipping_state' => isset($_GET['ship_state']) ? sanitize_text_field($_GET['ship_state']) : '',
        'shipping_postcode' => isset($_GET['ship_postcode']) ? sanitize_text_field($_GET['ship_postcode']) : '',
        'shipping_country' => isset($_GET['ship_country']) ? sanitize_text_field($_GET['ship_country']) : '',
        
        // Order notes
        'order_comments' => isset($_GET['notes']) ? sanitize_textarea_field($_GET['notes']) : '',
    );

    // Add products to cart if product_id is provided
    if (isset($_GET['product_id'])) {
        $product_id = intval($_GET['product_id']);
        $quantity = isset($_GET['quantity']) ? intval($_GET['quantity']) : 1;
        
        // Clear cart first if requested
        if (isset($_GET['clear_cart']) && $_GET['clear_cart'] === '1') {
            WC()->cart->empty_cart();
        }
        
        // Add product to cart
        if ($product_id > 0) {
            WC()->cart->add_to_cart($product_id, $quantity);
        }
    }
    
    // Set checkout fields
    foreach ($autofill_fields as $field => $value) {
        if (!empty($value)) {
            WC()->customer->set_props(array($field => $value));
        }
    }
    custom_autofill_checkout_js();
}
add_action('woocommerce_checkout_init', 'custom_autofill_checkout_fields');

/**
 * Add JavaScript to ensure the checkout form fields are populated
 */
function custom_autofill_checkout_js() {
    wc_enqueue_js("
        // Get URL parameters
        const urlParams = new URLSearchParams(window.location.search);
        
        // Map URL parameters to checkout fields
        const fieldMap = {
            'fname': '#billing_first_name',
            'lname': '#billing_last_name',
            'email': '#billing_email',
            'phone': '#billing_phone',
            'company': '#billing_company',
            'address1': '#billing_address_1',
            'address2': '#billing_address_2',
            'city': '#billing_city',
            'state': '#billing_state',
            'postcode': '#billing_postcode',
            'country': '#billing_country',
            'ship_fname': '#shipping_first_name',
            'ship_lname': '#shipping_last_name',
            'ship_company': '#shipping_company',
            'ship_address1': '#shipping_address_1',
            'ship_address2': '#shipping_address_2',
            'ship_city': '#shipping_city',
            'ship_state': '#shipping_state',
            'ship_postcode': '#shipping_postcode',
            'ship_country': '#shipping_country',
            'notes': '#order_comments'
        };
        
        // Fill form fields from URL parameters
        Object.entries(fieldMap).forEach(([param, selector]) => {
            if (urlParams.has(param)) {
                $(selector).val(urlParams.get(param)).trigger('change');
            }
        });
        
        // Handle shipping to different address
        if (urlParams.has('ship_different') && urlParams.get('ship_different') === '1') {
            $('#ship-to-different-address-checkbox').prop('checked', true).trigger('change');
        }
        
        // Ensure fields update when form refreshes
        $(document.body).on('updated_checkout', function() {
            // Re-apply values after checkout updates
            Object.entries(fieldMap).forEach(([param, selector]) => {
                if (urlParams.has(param)) {
                    $(selector).val(urlParams.get(param)).trigger('change');
                }
            });
        });
    ");
}

It should better work.

Note that woocommerce_checkout_init is only triggered on WooCommerce checkout page.

Your helper function generate_autofill_checkout_url remains unchanged.

4
  • Hi there, thanks for the help. Just a quick question, i am new to woocommerce/wordpress and setting this all up. How would i set up this from the back end, because im putting my code into the functions.php for my theme but is there anything else i would need to do at all? Sorry if im asking too much..
    – boshuua
    Commented yesterday
  • First, as a new user on stack overflow, please take the quick visual tour (20 seconds), to better understand how things work basically.… Note: I am not sure that your code will work if Checkout blocks is enabled, it should only work with legacy Classic Checkout… See Customizing the Cart and Checkout Pages and Switch to back to classic checkout page Commented yesterday
  • Changes: I removed unnecessary is_checkout() from the first function. Commented yesterday
  • Cheers thank you, sorry to be any trouble..
    – boshuua
    Commented yesterday

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.