{"title":"Google address autocomplete","slug":"google-address-autocomplete","url":"https://support.storeconnect.com/articles/google-address-autocomplete","url_markdown":"https://support.storeconnect.com/articles/google-address-autocomplete.md","subtitle":null,"summary":"Enable Google Maps address autocomplete at checkout by configuring your API key and supported countries as store variables, then adding the Places API script to your Liquid theme template.","type":"Help_Documentation","video_url":"","keywords":"google maps, google places api, address autocomplete, checkout, store variables, liquid theme","last_modified":"2026-08-21T07:12:35+0000","body_markdown":"## What you need \n\n-   A [Google Maps API Key](https://developers.google.com/maps/documentation/embed/get-api-key)\n-   The [ISO code for each country](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) you want to support using this method\n\n## Add store variables \n\n1.  Open your store in StoreConnect.\n2.  In the **Store Variables** section, click **New** and add the following variables:\n    1.  **Name** - Address Auto-complete Google API\n        **Key** - `google_autocomplete_api_key`\n        **Value** - your Google Maps API key\n        **Available in Liquid** - `true`\n    2.  **Name** - Address Auto-complete Countries\n        **Key** - `autocomplete_countries`\n        **Value** - 2-character, comma-separated ISO code for each country you want to support, for example `US, CA` (Google supports up to five at a time)\n        **Available in Liquid** - `true`\n    3.  **Name** - Default Auto-complete Country\n        **Key** - `default_autocomplete_country`\n        **Value** - 2-character ISO code for one country you want to include\n        **Available in Liquid** - `true`\n3.  Click **Save**.\n\n## Update your theme layout template (in Liquid)\n\n1.  Open your theme record in StoreConnect.\n2.  Open the applicable **Theme Template**. \n3.  If your theme doesn't already have a theme template, grab it here and create one for your theme: [theme.liquid](https://github.com/GetStoreConnect/base-theme/blob/main/templates/layouts/theme.liquid \"theme.liquid\")\n4.  Add the following code to the very bottom of the theme template **Content** section. This ensures address fields have loaded before the layout runs.\n5.  Select **Save**.\n\n\n```liquid\n\n{%- assign google_autocomplete_api_key = store_variables['google_autocomplete_api_key'] | default: blank -%}\n{%- assign autocomplete_countries = store_variables['autocomplete_countries'] | default: 'AU,US' | strip -%}\n{%- assign default_autocomplete_country = store_variables['default_autocomplete_country'] | default: 'AU' -%}\n\n// Google Maps loader\n(g=\u003e{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=()=\u003eh||(h=new Promise(async(f,n)=\u003e{await (a=m.createElement(\"script\"));e.set(\"libraries\",[...r]+\"\");for(k in g)e.set(k.replace(/[A-Z]/g,t=\u003e\"_\"+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=()=\u003eh=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)=\u003er.add(f)\u0026\u0026u().then(()=\u003ed[l](f,...n))})\n({key: \"{{ google_autocomplete_api_key }}\", v: \"weekly\"});\n\nconst allowedCountries = '{{ autocomplete_countries }}'.split(',').map(c =\u003e c.trim()).filter(c =\u003e c);\n\nlet autocomplete;\nlet address1Field;\nlet address2Field;\nlet cityField;\nlet postalField;\nlet countryField;\nlet stateField;\n\nasync function initAutocomplete() {\n    try {\n        // Import the places library\n        await google.maps.importLibrary('places');\n\n        // Get form fields\n        address1Field = document.querySelector('#shipping_address_line_1');\n        address2Field = document.querySelector('#shipping_address_line_2');\n        cityField = document.querySelector('#shipping_city__customer_information');\n        postalField = document.querySelector('#shipping_postal_code__customer_information');\n        countryField = document.querySelector('#shipping_country__customer_information');\n        stateField = document.querySelector('#shipping_state__customer_information');\n\n        if (!address1Field) {\n            console.error('Address field not found');\n            return;\n        }\n\n        // Set default country\n        if (countryField) {\n            countryField.value = '{{ default_autocomplete_country }}';\n            countryField.dispatchEvent(new Event('change', { bubbles: true }));\n        }\n\n        // Update placeholder\n        address1Field.placeholder = 'Start typing your address...';\n\n        // Create autocomplete on the existing input using the Autocomplete class\n        autocomplete = new google.maps.places.Autocomplete(address1Field, {\n            componentRestrictions: { country: ['{{ default_autocomplete_country }}'] },\n            fields: ['address_components', 'geometry'],\n            types: ['address']\n        });\n\n        // Listen for place selection\n        autocomplete.addListener('place_changed', fillInAddress);\n\n        // Listen for country changes\n        if (countryField) {\n            countryField.addEventListener('change', function() {\n                const selectedCountry = this.value;\n\n                if (selectedCountry \u0026\u0026 allowedCountries.includes(selectedCountry)) {\n                    // Update autocomplete country restriction\n                    autocomplete.setComponentRestrictions({\n                        country: [selectedCountry]\n                    });\n\n                    // Clear form fields when country changes\n                    if (address1Field) address1Field.value = '';\n                    if (address2Field) address2Field.value = '';\n                    if (cityField) cityField.value = '';\n                    if (postalField) postalField.value = '';\n                    if (stateField) stateField.value = '';\n                }\n            });\n        }\n\n    } catch (error) {\n        console.error('Failed to initialize autocomplete:', error);\n    }\n}\n\nfunction fillInAddress() {\n    const place = autocomplete.getPlace();\n\n    if (!place.address_components) {\n        console.log('No address components found');\n        return;\n    }\n\n    let address1 = '';\n    let postcode = '';\n    let city = '';\n    let state = '';\n\n    // Parse address components\n    for (const component of place.address_components) {\n        const types = component.types;\n\n        if (types.includes('street_number')) {\n            address1 = component.long_name + ' ';\n        }\n        if (types.includes('route')) {\n            address1 += component.long_name;\n        }\n        if (types.includes('locality')) {\n            city = component.long_name;\n        }\n        if (types.includes('administrative_area_level_1')) {\n            state = component.short_name;\n        }\n        if (types.includes('postal_code')) {\n            postcode = component.long_name;\n        }\n    }\n\n    // Fill in the form fields\n    address1Field.value = address1.trim();\n    if (cityField) cityField.value = city;\n    if (postalField) postalField.value = postcode;\n\n    // Set state - give state dropdown time to populate\n    if (stateField \u0026\u0026 state) {\n        setTimeout(() =\u003e {\n            stateField.value = state;\n            stateField.dispatchEvent(new Event('change', { bubbles: true }));\n        }, 500);\n    }\n\n    // Focus on address line 2 for apartment/unit number\n    if (address2Field) {\n        address2Field.focus();\n    }\n\n    console.log('Address filled:', { address1, city, state, postcode });\n}\n\n// Initialize when DOM is ready\nif (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', initAutocomplete);\n} else {\n    initAutocomplete();\n}\n\n/* Style the autocomplete dropdown */\n.pac-container {\n    z-index: 10000 !important;\n    border-radius: 8px;\n    margin-top: 4px;\n    box-shadow: 0 2px 6px rgba(0,0,0,0.3);\n    font-family: inherit;\n}\n\n.pac-item {\n    padding: 10px 12px;\n    cursor: pointer;\n    font-size: 14px;\n    line-height: 1.4;\n}\n\n.pac-item:hover {\n    background-color: #f5f5f5;\n}\n\n.pac-item-query {\n    font-size: 15px;\n    color: #333;\n}\n\n.pac-matched {\n    font-weight: 600;\n}\n```\n"}