Address autocomplete in the WooCommerce checkout
Install the Lynbro Danadresse plugin or a small mu-plugin for address autocomplete in WooCommerce, and validate the address when the order is placed.
WooCommerce has two checkouts: the classic one (the [woocommerce_checkout] shortcode) and the block checkout, which is the default in new shops. Both are made of plain input fields, so the address widget can attach to them. Here are the two routes: our WordPress plugin and a small mu-plugin that you control.
1. The plugin: Lynbro Danadresse
Install Lynbro Danadresse from wordpress.org:
- In WordPress go to Plugins → Add New, search for "Lynbro Danadresse", click Install and Activate.
- Create a key under Keys. Use a normal live key without allowed domains: the plugin calls the API from your own server, and a domain-locked key is refused there because a server call has no
Origin. - Paste the key under Lynbro → Danadresse → Settings. The Status tab runs a test lookup with the key.
- Under Integrations, WooCommerce is switched on by default.
What the plugin does in WooCommerce:
- Autocomplete in the classic checkout, the block checkout and the address forms under My Account. Postcode and city are filled for you.
- When an order with a Danish delivery address is placed, the address is checked against the register (datavask). The result (exact, close or not recognised) is saved on the order and shown to the shop admin. You can choose to stop orders with clearly invalid addresses. If the API cannot be reached, the checkout is never blocked.
- Statistics shows the site's lookups per day, and Log explains recent errors in plain words.
If you prefer your own code, or want the browser to call the API directly with a domain-locked key, use the mu-plugin below.
2. Create a browser key for the mu-plugin
The mu-plugin calls the API straight from the browser. Create a live key under Keys and lock it to myshop.dk and www.myshop.dk under Allowed domains. See Browser keys and allowed domains.
3. Add the mu-plugin
Save the file as wp-content/mu-plugins/danadresse.php. WordPress loads files in mu-plugins automatically.
<?php /** * Plugin Name: Danadresse autocomplete (WooCommerce) */ if (!defined('ABSPATH')) { exit; } add_action('wp_enqueue_scripts', function () { if (!function_exists('is_checkout') || !(is_checkout() || is_account_page())) { return; } wp_enqueue_script( 'danadresse-autocomplete', 'https://danadresse.dk/static/js/danadresse-autocomplete-1.0.0.js', [], null, true ); wp_add_inline_script('danadresse-autocomplete', <<<'JS' const API_KEY = "YOUR_BROWSER_KEY"; function setField(el, value, events) { if (!el || value == null) return; const setter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value").set; setter.call(el, value); for (const type of events || ["input", "change"]) { el.dispatchEvent(new Event(type, { bubbles: true })); } } function streetLine(a) { let line = a.vejnavn + " " + a.husnr; if (a.etage) line += ", " + a.etage + "."; if (a["dør"]) line += " " + a["dør"]; return line; } // Classic: billing_address_1 → billing_postcode. Blocks: billing-address_1 → billing-postcode. function bind(input) { DanadresseAutocomplete.attach(input, { apiKey: API_KEY, onSelect(a) { setField(input, streetLine(a), ["change"]); setField(document.getElementById(input.id.replace("address_1", "postcode")), a.postnr); setField(document.getElementById(input.id.replace("address_1", "city")), a.postnrnavn); }, }); } function bindAll() { document .querySelectorAll("#billing_address_1, #shipping_address_1, #billing-address_1, #shipping-address_1") .forEach(bind); } bindAll(); // The block checkout renders its fields later, and again when the customer switches address. new MutationObserver(bindAll).observe(document.body, { childList: true, subtree: true }); JS ); });
The widget attaches to a field only once, so it is harmless that bindAll runs on every change to the page.
4. Test both checkouts
Type an address, pick a suggestion, and place a test order. Check in the order that street, postcode and city were saved. The block checkout is built with React. The code fires input and change events so React notices the value, but check it on your WooCommerce version before you go live. You can see the field ids with Inspect.
5. Optional: validate on order
With a server key without a domain lock you can check the address before the order is created. The code sends street, number and postcode to /datavask/adgangsadresser, which checks the building. Floor and door are not checked. The hook runs in the classic checkout only. The key is read from the DANADRESSE_API_KEY environment variable.
<?php add_action('woocommerce_after_checkout_validation', function (array $data, WP_Error $errors) { $prefix = !empty($data['ship_to_different_address']) ? 'shipping_' : 'billing_'; if (($data[$prefix . 'country'] ?? '') !== 'DK') { return; } // Street and number only (before the first comma) + postcode. $street = trim(strtok((string) ($data[$prefix . 'address_1'] ?? ''), ',')); $betegnelse = $street . ', ' . ($data[$prefix . 'postcode'] ?? ''); $res = wp_remote_get( 'https://api.danadresse.dk/datavask/adgangsadresser?' . http_build_query(['betegnelse' => $betegnelse]), ['headers' => ['X-Api-Key' => getenv('DANADRESSE_API_KEY')], 'timeout' => 5] ); if (is_wp_error($res) || wp_remote_retrieve_response_code($res) !== 200) { return; // the API did not answer: let the order through } $vask = json_decode(wp_remote_retrieve_body($res), true); if (($vask['kategori'] ?? '') === 'C') { $errors->add('validation', 'We could not find the address. Check street, house number and postcode.'); } }, 10, 2);
Categories A and B are accepted, C stops the order. More in Address cleansing in checkout.
Next steps
- The WooCommerce page and the checkout overview
- Elementor forms on the same WordPress site
- The plugin on wordpress.org: Lynbro Danadresse
Related guides
Markdown source Spotted an error? Tell us API-reference (Swagger)