Google address autocomplete
On this page
What you need
- A Google Maps API Key
- The ISO code for each country you want to support using this method
Add store variables
- Open your store in StoreConnect.
- Select New in the Store Variables section and add the following variables.
- Name - Address Auto-complete Google API Key - google_autocomplete_api_key Value - your Google Maps API key Available in Liquid = true
- Name - Address Auto-complete Countries Key - autocomplete_countries Value - 2 character, comma separated ISO code for each country you want to support i.e. US, CA (Google supports up to five at a time) Available in Liquid = true
- Name - Default Auto-complete Country Key - default_autocomplete_country Value - 2 character ISO code for one country you want to include Available in Liquid = true
- Save.
Update your theme layout template (in Liquid)
- Open your theme record in StoreConnect.
- Open the applicable Theme Template.
- If your theme doesn’t already have a theme template, grab it here and create one for your theme: theme.liquid
- Add the following code to the very bottom of the theme template Content section. This ensures address fields have loaded before the layout runs.
- Select Save.
```liquid
| {%- assign google_autocomplete_api_key = store_variables[‘google_autocomplete_api_key’] | default: blank -%} | |
| {%- assign autocomplete_countries = store_variables[‘autocomplete_countries’] | default: ‘AU,US’ | strip -%} |
| {%- assign default_autocomplete_country = store_variables[‘default_autocomplete_country’] | default: ‘AU’ -%} |
// Google Maps loader
(g=>{var h,a,k,p=”The Google Maps JavaScript API”,c=”google”,l=”importLibrary”,q=”ib“,m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement(“script”));e.set(“libraries”,[…r]+””);for(k in g)e.set(k.replace(/[A-Z]/g,t=>”_“+t[0].toLowerCase()),g[k]);e.set(“callback”,c+”.maps.”+q);a.src=https://maps.${c}apis.com/maps/api/js?+e;d[q]=f;a.onerror=()=>h=n(Error(p+” could not load.”));a.nonce=m.querySelector(“script[nonce]”)?.nonce||”“;m.head.append(a)}));d[l]?console.warn(p+” only loads once. Ignoring:”,g):d[l]=(f,…n)=>r.add(f)&&u().then(()=>dl)})
({key: “{{ google_autocomplete_api_key }}”, v: “weekly”});
const allowedCountries = ‘{{ autocomplete_countries }}’.split(‘,’).map(c => c.trim()).filter(c => c);
let autocomplete; let address1Field; let address2Field; let cityField; let postalField; let countryField; let stateField;
async function initAutocomplete() { try { // Import the places library await google.maps.importLibrary(‘places’);
// Get form fields
address1Field = document.querySelector('#shipping_address_line_1');
address2Field = document.querySelector('#shipping_address_line_2');
cityField = document.querySelector('#shipping_city__customer_information');
postalField = document.querySelector('#shipping_postal_code__customer_information');
countryField = document.querySelector('#shipping_country__customer_information');
stateField = document.querySelector('#shipping_state__customer_information');
if (!address1Field) {
console.error('Address field not found');
return;
}
// Set default country
if (countryField) {
countryField.value = '{{ default_autocomplete_country }}';
countryField.dispatchEvent(new Event('change', { bubbles: true }));
}
// Update placeholder
address1Field.placeholder = 'Start typing your address...';
// Create autocomplete on the existing input using the Autocomplete class
autocomplete = new google.maps.places.Autocomplete(address1Field, {
componentRestrictions: { country: ['{{ default_autocomplete_country }}'] },
fields: ['address_components', 'geometry'],
types: ['address']
});
// Listen for place selection
autocomplete.addListener('place_changed', fillInAddress);
// Listen for country changes
if (countryField) {
countryField.addEventListener('change', function() {
const selectedCountry = this.value;
if (selectedCountry && allowedCountries.includes(selectedCountry)) {
// Update autocomplete country restriction
autocomplete.setComponentRestrictions({
country: [selectedCountry]
});
// Clear form fields when country changes
if (address1Field) address1Field.value = '';
if (address2Field) address2Field.value = '';
if (cityField) cityField.value = '';
if (postalField) postalField.value = '';
if (stateField) stateField.value = '';
}
});
}
} catch (error) {
console.error('Failed to initialize autocomplete:', error);
} }
function fillInAddress() { const place = autocomplete.getPlace();
if (!place.address_components) {
console.log('No address components found');
return;
}
let address1 = '';
let postcode = '';
let city = '';
let state = '';
// Parse address components
for (const component of place.address_components) {
const types = component.types;
if (types.includes('street_number')) {
address1 = component.long_name + ' ';
}
if (types.includes('route')) {
address1 += component.long_name;
}
if (types.includes('locality')) {
city = component.long_name;
}
if (types.includes('administrative_area_level_1')) {
state = component.short_name;
}
if (types.includes('postal_code')) {
postcode = component.long_name;
}
}
// Fill in the form fields
address1Field.value = address1.trim();
if (cityField) cityField.value = city;
if (postalField) postalField.value = postcode;
// Set state - give state dropdown time to populate
if (stateField && state) {
setTimeout(() => {
stateField.value = state;
stateField.dispatchEvent(new Event('change', { bubbles: true }));
}, 500);
}
// Focus on address line 2 for apartment/unit number
if (address2Field) {
address2Field.focus();
}
console.log('Address filled:', { address1, city, state, postcode }); }
// Initialize when DOM is ready if (document.readyState === ‘loading’) { document.addEventListener(‘DOMContentLoaded’, initAutocomplete); } else { initAutocomplete(); }
/* Style the autocomplete dropdown */ .pac-container { z-index: 10000 !important; border-radius: 8px; margin-top: 4px; box-shadow: 0 2px 6px rgba(0,0,0,0.3); font-family: inherit; }
.pac-item { padding: 10px 12px; cursor: pointer; font-size: 14px; line-height: 1.4; }
.pac-item:hover { background-color: #f5f5f5; }
.pac-item-query { font-size: 15px; color: #333; }
.pac-matched { font-weight: 600; } ```