# Address autocomplete in PrestaShop 1.7.8 to 9

> Install the Danadresse module for checkout autocomplete and an address check on every order, or build a small module of your own that loads the widget.
>
> https://danadresse.dk/en/guides/prestashop · verified 2026-11-02
There is a PrestaShop module for Danadresse: `danadresse` (MIT licence) for PrestaShop 1.7.8, 8.x and 9.x. It gives the checkout, the address book and registration address autocomplete with postcode and city, works in the classic and hummingbird themes, and checks the address of every new order. If you would rather write the code yourself, the second half of this guide shows a small module of your own.

## 1. Create two keys

Under [Keys](/dashboard/keys):

- a **browser key** for the shop's pages. Add the shop's domains under **Allowed domains**, e.g. `myshop.dk, www.myshop.dk`. A domain-locked key only works there. See [Browser keys and allowed domains](/en/guides/browser-noegler-domaener).
- a **server key** without domains for the order check. It is never sent to the browser.

## 2. Install the module

Download the module ZIP (`danadresse-prestashop-<version>.zip`) from the [download page](/en/integrationer/download#prestashop) — don't unpack it. Then go to **Modules → Module Manager → Upload a module**, choose the file, and click **Configure**. Or unpack it into `modules/danadresse/` and install it from the command line:

```bash id=module-install run=no
php bin/console prestashop:module install danadresse
```

The installation creates one table, `PREFIX_danadresse_check`, with one row per checked order.

## 3. Configure

**Storefront**: switch on *Enable address autocomplete* (off by default) and paste the browser key. *Check typed addresses* and *Fill city from postcode* are on by default. The script is loaded on the checkout, the address book and the registration page, and it ships with the module.

**Order validation**: switch on *Validate addresses of new orders*, paste the server key, and choose delivery, invoice or both. The result is added to the order's private note, which the customer never sees. The order check needs PHP's curl extension.

## 4. Test

1. Put a product in the cart and go to checkout as a guest.
2. Under *Addresses*, type `Rentemestervej 8` and pick the suggestion.
3. Postcode `2400` and city `København NV` are filled.
4. Place the order. Under **Orders** the column *Address check* says *Valid*, and the order page has an *Address check* card.

`API refused the request (403)` in the browser console means the shop's domain is missing from the browser key. `401` means the browser key is missing or mistyped. *Not checked (API error)* on an order means the server key is wrong, curl is missing, or the API did not answer within 3 seconds. After an update, clear the cache under **Advanced Parameters → Performance**.

Third-party one-page-checkout modules usually keep PrestaShop's field names (`address1`, `postcode`, `city`), which the script recognises. If the checkout runs on its own controller, switch on *Load on every page*. Mark fields the script must leave alone with `data-danadresse="off"`.

## Without our module: a module of your own

PrestaShop's address form uses the same field names in checkout and under "My addresses": `address1`, `postcode` and `city`. A small module can therefore load the widget on both pages without changing your theme. When the customer changes country, the checkout fetches the form again with AJAX, so the script has to attach to new fields. The example module is also called `danadresse`, so install either ours or this one, not both.

### The module file

Create the folder `modules/danadresse/` and the file `danadresse.php`:

```php id=module-php run=syntax
<?php
if (!defined('_PS_VERSION_')) {
    exit;
}

class Danadresse extends Module
{
    public function __construct()
    {
        $this->name = 'danadresse';
        $this->tab = 'front_office_features';
        $this->version = '1.0.0';
        $this->author = 'Your shop';
        parent::__construct();
        $this->displayName = 'Danadresse autocomplete';
        $this->description = 'Danish address autocomplete on the address form.';
    }

    public function install()
    {
        return parent::install() && $this->registerHook('actionFrontControllerSetMedia');
    }

    public function hookActionFrontControllerSetMedia()
    {
        // Only checkout ("order") and the address page
        if (!in_array($this->context->controller->php_self, ['order', 'address'], true)) {
            return;
        }
        $this->context->controller->registerJavascript(
            'danadresse-widget',
            'https://danadresse.dk/static/js/danadresse-autocomplete-1.0.0.js',
            ['server' => 'remote', 'position' => 'bottom', 'priority' => 150]
        );
        $this->context->controller->registerJavascript(
            'danadresse-init',
            'modules/' . $this->name . '/views/js/init.js',
            ['position' => 'bottom', 'priority' => 151]
        );
    }
}
```

### The init script

Save the file as `modules/danadresse/views/js/init.js` and insert your browser key:

```js id=init-js run=syntax
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;
}

function bind(input) {
  const form = input.form || document;
  DanadresseAutocomplete.attach(input, {
    apiKey: API_KEY,
    onSelect(a) {
      setField(input, streetLine(a), ["change"]);
      setField(form.querySelector('input[name="postcode"]'), a.postnr);
      setField(form.querySelector('input[name="city"]'), a.postnrnavn);
    },
  });
}

function bindAll() {
  document.querySelectorAll('input[name="address1"]').forEach(bind);
}
bindAll();
// The checkout replaces the address form when the customer changes country.
new MutationObserver(bindAll).observe(document.body, { childList: true, subtree: true });
```

### Install and test

Zip the `danadresse` folder, upload it under **Modules → Module Manager → Upload a module**, and install it. Clear the cache under **Advanced Parameters → Performance**.

Test as a guest in checkout: type an address, pick a suggestion, and check that postcode and city are filled. If your theme uses other field names, right-click the field, choose **Inspect**, and adjust the selectors. The console shows `403 origin_not_allowed` if the domain is missing from the key.

### Check the address on the server

You can check the shipping address with the server key from the `actionValidateOrder` hook, which runs once the order has been created. Call `/datavask/adgangsadresser?betegnelse=Rådhuspladsen 1, 4200` with street, number and postcode. Category C means the address could not be found safely, so flag the order for a manual check. See [Address cleansing in checkout](/en/guides/datavask-i-checkout).

The widget searches Danish addresses only. If you sell abroad, customers can ignore the suggestions and keep typing.

## Next steps

- The [PrestaShop page](/en/integrationer/prestashop) on Integrations
- [Browser keys and allowed domains](/en/guides/browser-noegler-domaener)
- [Address cleansing in checkout](/en/guides/datavask-i-checkout)
