type:
integration
supports-foxycart-version-from:
2.0
system:
loqate
name:
Loqate
description:
Add Loqate address lookup and validation to your checkout
tags:
address lookup, address validation
date:
2021-01-20
version:
1.0
developer:
https://www.loqate.com

Loqate Address Validation

The following integration adds address autocompletion and validation using Loqate, with support for over 245 countries.

Requirements

Installation

Step 1: Signup with Loqate

This integration requires an account with Loqate, which you can sign up for on their website at https://www.loqate.com

Step 2: Add custom code

In your store's FoxyCart administration, proceed to the “configuration” section. If it's not already enabled, enable the option labelled “Add custom header and footer code to your templates”.

Then, within the “footer” textarea, paste the following code:

<style>
/*! Copyright © 2009-2021 Postcode Anywhere (Holdings) Ltd. (http://www.postcodeanywhere.co.uk)
 *
 * Address v3.91
 * Styles for the address control.
 *
 * WEB-1-12 20/01/2021 15:33:42
 */#fc .pca{margin:0;padding:0;position:static;border:none;box-sizing:content-box}#fc .pca *{box-sizing:content-box}#fc .pca .pcatext{font:9pt arial;color:#333}#fc .pca .pcalist{position:relative;list-style-type:none;list-style-position:outside;margin:0;padding:0;overflow-y:auto;overflow-x:hidden;background-color:#fafafa}#fc .pca .pcaitem{cursor:pointer;position:relative;margin:0;padding:9px 10px 9px 10px;padding:7px 10px;line-height:15px;text-align:left;white-space:nowrap;border:solid 1px transparent;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#e5e5e5;border-bottom-color:transparent;padding-right:22px;opacity:.8;color:#000}#fc .pca .pcaselected{color:#333;background-color:#e5f0ff;background-color:#f0f0f0;border-width:1px;border-style:solid;border-color:transparent;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#e5e5e5;border-bottom-color:transparent;opacity:1;color:#000}#fc .pca .pcalastitem{border-bottom:none}#fc .pca .pcadisableselect{-moz-user-select:none;-webkit-user-select:none}#fc .pca .pcaautocomplete{margin:0;padding:0;border-width:1px;border-style:solid;border-color:#ccc;border-bottom:0;background:0;box-shadow:0 8px 17px 0 rgba(0,0,0,.2);width:inherit;position:absolute;z-index:9999999999}#fc .pca .pcaanchor{margin:0;padding:0;border:0;background:0}#fc .pca .pcaanchor .pcachain{position:relative}#fc .pca .pcaautocomplete .pcaheader{background-color:#fafafa;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#ccc;color:#969696}#fc .pca .pcaautocomplete .pcamessage{padding:8px 10px;line-height:18px}#fc .pca .pcaautocomplete .pcalist{height:244px;width:auto;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#ccc}#fc .pca .pcaautocomplete .pcafooter{border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#ccc;background-color:#fafafa;height:30px;box-sizing:content-box;min-width:138px;overflow:hidden}#fc .pca .pcanotification{background-color:#fafafa;padding:8px 10px 8px 10px;box-shadow:0 2px 5px 0 rgba(0,0,0,.26);border-radius:2px;position:absolute;z-index:100000;transition:opacity .5s ease-in-out;-moz-transition:opacity .5s ease-in-out;-webkit-transition:opacity .5s ease-in-out;opacity:1;display:none}#fc .pca .pcanotification.pcavisible{display:block}#fc .pca .pcanotification.pcafade{opacity:0}#fc .pca .pcanotification.pcaerror{background-color:#db7f83;color:#fff}#fc .pca .pcaautocomplete .pcafooter .pcamessage{font:bold 9pt arial;color:#969696;margin:9px 0 0 5px;padding:0;position:relative;float:right}#fc .pca .pcamodal{position:fixed;top:50%;left:50%;z-index:100000}#fc .pca .pcamodal .pcalist{height:244px;width:auto;min-width:200px;min-height:100px}#fc .pca .pcamodal .pcaborder{position:absolute;width:100%;height:100%;top:0;left:0;background-color:#000;border-radius:0;opacity:.2}#fc .pca .pcamodal .pcaframe{position:relative;margin:12px;background-color:#f5f7f9;border-radius:0;border-width:1px;border-style:solid;border-color:#c8cacc}#fc .pca .pcamodal .pcacontent{position:relative;padding:15px}#fc .pca .pcamodal .pcacontent .pcainputrow{width:450px;text-align:right}#fc .pca .pcamodal .pcacontent .pcainputrow input{width:300px;border-width:1px;border-style:solid;border-color:#d4d4d4;padding:8px;margin:15px;background:#fff}#fc .pca .pcamodal .pcacontent .pcainputrow input:invalid{-webkit-box-shadow:0 0 1.5px 1px red;-moz-box-shadow:0 0 1.5px 1px red;box-shadow:0 0 1.5px 1px red}#fc .pca .pcamodal .pcacontent .pcainputrow .pcahalf{width:126px}#fc .pca .pcamodal .pcacontent .pcainputrow label{font:bold 14px arial;color:#444}#fc .pca .pcamodal .pcaheader{position:relative;top:0;left:0;border-top:1px solid #e1e3e5;border-bottom:1px solid #c8cacc;border-radius:0;background:#e1e3e5;background:-moz-linear-gradient(top,#e1e3e5 0,#e1e3e5 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#e1e3e5),color-stop(100%,#e1e3e5))}#fc .pca .pcamodal .pcaheader .pcatitle{font:bold 18px arial;color:#005db9;margin:15px}#fc .pca .pcamodal .pcafooter{position:relative;bottom:0;left:0;border-top:1px solid #c8cacc;background:#fff}#fc .pca .pcamodal .pcafooter .pcabutton{width:150px;margin:15px}#fc .pca .pcafullscreen{position:fixed;top:0;left:0;height:100%;width:100%}#fc .pca .pcamask{background-color:#000;opacity:.4;z-index:100000}#fc .pca .pcabutton{font:bold 14px arial;color:#444;border:1px solid #d4d4d4;border-radius:0;padding:8px;cursor:pointer;background:#f5f7f9;background:-moz-linear-gradient(top,#f5f7f9 0,#f5f7f9 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f5f7f9),color-stop(100%,#f5f7f9))}#fc .pca .pcatooltip{position:absolute;z-index:100000}#fc .pca .pcatooltip .pcabackground{position:absolute;height:100%;width:100%;background-color:#000;border-radius:5px;opacity:.6}#fc .pca .pcatooltip .pcamessage{position:relative;padding:5px;font:9pt arial;color:#fff}#fc .pca .pcabutton:hover{color:#444}#fc .pca .pcalink{font:bold 9pt arial;cursor:pointer}#fc .pca .pcaclear{clear:both}.pcaflag{width:14px;height:12px;position:absolute;font-size:0;background-image:url(//services.postcodeanywhere.co.uk/images/flags16x16.png);-moz-box-shadow:0 1px 2px rgba(128,128,128,.3);-webkit-box-shadow:0 1px 2px rgba(128,128,128,.3);box-shadow:0 1px 2px rgba(128,128,128,.3)}#fc .pca .pcaautocomplete .pcafooter .pcaflagbutton{width:31px;height:21px;position:relative;float:right;padding:5px 6px;cursor:pointer;background-image:url(//services.postcodeanywhere.co.uk/images/icons/flag_clear_down.png);background-position:5px 5px;background-repeat:no-repeat}#fc .pca .pcaautocomplete .pcafooter .pcaflagbutton:hover{background-image:url(//services.postcodeanywhere.co.uk/images/icons/flag_clear_down_hover.png)}#fc .pca .pcaautocomplete .pcafooter .pcaflagbutton .pcaflag{top:9px;left:9px}#fc .pca .pcaautocomplete .pcaflaglabel{position:relative;left:26px}#fc .pca .pcacountrylist .pcafooter .pcaflagbutton{background-image:url(//services.postcodeanywhere.co.uk/images/icons/flag_clear_up.png)}#fc .pca .pcacountrylist .pcafooter .pcaflagbutton:hover{background-image:url(//services.postcodeanywhere.co.uk/images/icons/flag_clear_up_hover.png)}#fc .pca .pcaexpandable{background-image:url(//services.postcodeanywhere.co.uk/images/icons/captureplus/chevron.png);background-repeat:no-repeat;background-position-x:99%;background-position-y:50%;background-position:right 7px center}#fc .pca .pcaautocomplete .pcafooter .geoLocationIcon{width:21px;height:21px;font-size:0;margin:0 5px 0 0;padding:5px 0 5px 5px;position:relative;float:right;cursor:pointer;background-image:url(//services.postcodeanywhere.co.uk/images/icons/captureplus/geolocationicon.svg);background-position:right;background-repeat:no-repeat;color:#7e8593;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"!important;visibility:hidden}#fc .pca .pcaautocomplete .pcafooter .geoLocationIcon.active{visibility:visible}#fc .pca .pcaautocomplete .pcafooter .geoLocationIcon.working{background-image:url(//services.postcodeanywhere.co.uk/images/icons/captureplus/loader.gif)}#fc .pca .pcaautocomplete .pcafooter .geoLocationMessage{color:#7e8593;padding:9px 0;position:relative;float:right;cursor:pointer;font-size:11px;visibility:hidden}#fc .pca .pcaautocomplete .pcafooter .geoLocationMessage.active{visibility:visible}#fc .pca .pcaautocomplete .pcafooter .pcalogo{width:68px;height:16px;margin:7px 0 0 7px;font-size:0;position:relative;float:left;background-repeat:no-repeat;background-size:contain;background-image:url(//services.postcodeanywhere.co.uk/images/icons/captureplus/loqatelogoinverted.svg)}#fc .pca .pcaautocomplete .pcafooter .adsylogo{width:68px;height:16px;margin:7px 0 0 7px;font-size:0;position:relative;float:left;background-repeat:no-repeat;background-size:contain;background-image:url(//services.postcodeanywhere.co.uk/images/icons/captureplus/loqatelogoinverted.svg)}#fc .pca .pcaautocomplete .pcafooter .aclogo{width:112px;height:15px;font-size:0;margin:8px 5px 8px 11px;position:relative;float:left;background-image:url(//services.postcodeanywhere.co.uk/images/icons/captureplus/address_complete_logo_en.png)}#fc .pca .pcaautocomplete .pcafooter .aclogo.pcalogofr{width:118px;background-image:url(//services.postcodeanywhere.co.uk/images/icons/captureplus/address_complete_logo_fr.png)}#fc .pca .pcaautocomplete .pcafooter .dtlogo{width:100px;height:14px;font-size:0;margin:9px 5px 6px 9px;position:relative;float:left;background-image:url(//services.postcodeanywhere.co.uk/images/icons/captureplus/dt_express_capture_logo.png)}#fc .pca .pcaautocomplete .pcafooter .anlogo{width:129px;height:11px;font-size:0;margin:10px 5px 9px 9px;position:relative;float:left;background-image:url(//services.postcodeanywhere.co.uk/images/icons/captureplus/address_now_logo.png)}#fc .pca .pcaitem .pcadescription{color:#6b6b6b;margin-left:8px}#fc .pca .pcaitem .pcautilitytype{padding-right:8px;font-style:italic}
 </style>
<script type="text/javascript" src="https://services.postcodeanywhere.co.uk/js/address-3.91.js"></script>
{% if context == "checkout" %}
<script>
var _LOQATE_API_KEY = "XX11-XX11-XX11-XX11";
 
FC.client.on('render.done', initializeLoqate);
FC.client.on("ready.done", function() { initializeLoqate({"block_id": "checkout"}); });
 
function initializeLoqate(params) {
    // Not compatible with the native postcode lookup options or multiship
    if (FC.json.config.template_config.postal_code_lookup.usage == "enabled" || FC.json.has_multiship) return;
 
    if ((params.block_id === 'customer_shipping' || params.block_id === 'checkout') && FC.json.shipping_address.has_shippable_products) {
        var shipping_countries = [];
        for (var country in FC.json.config.locations) {
            if (!FC.json.config.locations_shipping.hasOwnProperty(country) || FC.json.config.locations_shipping[country] !== "*") {
                shipping_countries.push(FC.json.config.locations[country].cc3);
            }
        }
        var shipping_options = { key: _LOQATE_API_KEY, countries: { codesList: shipping_countries.join(',') }, setCountryByIP: false };
        var shipping_fields = [
            { element: "shipping_company", field: "Company", mode: pca.fieldMode.DEFAULT | pca.fieldMode.PRESERVE },
            { element: "shipping_address1", field: "Line1" },
            { element: "shipping_address2", field: "Line2", mode: pca.fieldMode.POPULATE },
            { element: "shipping_city", field: "City", mode: pca.fieldMode.POPULATE },
            { element: "shipping_region", field: "Province", mode: pca.fieldMode.POPULATE },
            { element: "shipping_postal_code", field: "PostalCode" },
            { element: "shipping_country", field: "CountryIso2", mode: pca.fieldMode.POPULATE | pca.fieldMode.COUNTRY }
        ];
        var shippingControl = new pca.Address(shipping_fields, shipping_options);
        shippingControl.listen("populate", function (address, variations) {
            populateLoqate('shipping', address);
        });
    }
 
    if ((params.block_id === 'customer_billing' || params.block_id === 'checkout') && (FC.json.use_different_addresses == 1 || !FC.json.shipping_address.has_shippable_products)) {
        var billing_countries = [];
        for (var country in FC.json.config.locations) {
            if (!FC.json.config.locations_billing.hasOwnProperty(country) || FC.json.config.locations_billing[country] !== "*") {
                billing_countries.push(FC.json.config.locations[country].cc3);
            }
        }
        var billing_options = { key: _LOQATE_API_KEY, countries: { codesList: billing_countries.join(',') }, setCountryByIP: false };
        var billing_fields = [
            { element: "billing_company", field: "Company", mode: pca.fieldMode.DEFAULT | pca.fieldMode.PRESERVE },
            { element: "billing_address1", field: "Line1" },
            { element: "billing_address2", field: "Line2", mode: pca.fieldMode.POPULATE },
            { element: "billing_city", field: "City", mode: pca.fieldMode.POPULATE },
            { element: "billing_region", field: "Province", mode: pca.fieldMode.POPULATE },
            { element: "billing_postal_code", field: "PostalCode" },
            { element: "billing_country", field: "CountryIso2", mode: pca.fieldMode.POPULATE | pca.fieldMode.COUNTRY }
        ];
        var billingControl = new pca.Address(billing_fields, billing_options);
        billingControl.listen("populate", function (address, variations) {
            populateLoqate('billing', address);
        });
    }
}
 
function populateLoqate(prefix, address) {
    if ($('[data-fc-id="' + prefix + '_country"]').val() != address.CountryIso2) {
        $('[data-fc-id="' + prefix + '_country"]').val(address.CountryIso2).change();
    }
    if ($('[data-fc-id="' + prefix + '_region"]')[0].nodeName === "INPUT") {
        $('[data-fc-id="' + prefix + '_region"]').val(address.ProvinceName).trigger("focusout");
    } else {
        $('[data-fc-id="' + prefix + '_region"]').val(address.Province).trigger("focusout");
        $('[data-fc-id="' + prefix + '_region_name"]').val(address.ProvinceName);
    }
    $('#' + prefix + '_postal_code').val(address.PostalCode).trigger("focusout");
    $('#' + prefix + '_address1').val(address.Line1).trigger("focusout");
    $('#' + prefix + '_address2').val(address.Line2).trigger("focusout");
    $('#' + prefix + '_city').val(address.City).trigger("focusout").trigger("change");
}
</script>
{% endif %}

Step 3: Customise code

At the top of the code, you'll need to update the following line with your own API Key from your Loqate account:

var _LOQATE_API_KEY = "XX11-XX11-XX11-XX11";

You can get this API key by creating a service for your Foxy checkout within your Loqate account. To do that:

  1. In the Loqate account administration, click the “Add Service” button in the top right
  2. In the options for adding a new service, select “API Key” from the bottom row of the options
  3. This will load a page with your new service.
  4. Go to the “Configuration” tab and give it a name (like “Foxy Checkout” for example).
  5. Go to the “Limits” tab and under “Limit by URL”, enter your Foxy store subdomain. That will look like https://yourstore.foxycart.com, or if you're using a custom subdomain, whatever you've configured as the custom store subdomain.
  6. Press the “Save” button after configuring any other options as desired.
  7. Back on the “Configuration” tab, copy the “Key” from the top of the panel, this is what you'll need to set on the API key as noted above.

Step 4: Turn off native postcode lookup

As the new integration will take care of auto-filling the customers address, the normal postcode lookup functionality isn't needed, and can cause conflicts when enabled.

To turn that off, within the “configuration” section of the Foxy administration, uncheck the checkbox for “Enable city and region lookup by postal code”

Step 6: Save and test!

After you've made all of the modifications to your store's configuration in the Foxy administration, save the configuration.

Now you're ready to test! Add a product to your cart, head to the checkout and you should see the address auto-complete as you type.

Site Tools