When it comes to user-entered address data, I don’t trust anyone—not because users are malicious, but because typos and inconsistencies are inevitable. That’s why I wanted to integrate Google Maps address autocomplete into Oracle APEX, enabling users to search and select validated address data that populates directly into form fields based on a real-world location selected via Google Maps.
What follows is a walk-through of how I embedded a Google Maps-powered address validator into an Oracle APEX app. I’ll cover both the visual version with a map and autocomplete widget, and the simpler option that ties autocomplete directly to a form field.
Why This Matters
Accurate address data is critical—especially in applications involving shipping, billing, or location-based logic. With Google Places, users can search using business names or partial addresses, and Google will return structured data that you can use to populate your APEX fields automatically. This tutorial demonstrates a reliable method for integrating Oracle APEX Google Maps address autocomplete, ensuring your forms collect cleaner, verified address data with minimal user effort.
Also worth noting: Google made significant changes to its Maps and Places APIs in 2024, so many online tutorials are now outdated. The method below reflects the current API structure and offers a reliable solution as of mid-2025.
Prerequisites
Before you begin, you’ll need:
- A Google Cloud project
- A valid Google Maps API key
- The Maps JavaScript API, Places API, and Marker API enabled
- An APEX page with the following page items:
- :P1_NAME
- :P1_BILLINGSTREET
- :P1_BILLINGCITY
- :P1_BILLINGSTATE
- :P1_BILLINGPOSTALCODE
How Oracle APEX Integrates Google Maps Address Autocomplete
I created a static content region in APEX that holds both the Google Map and the autocomplete widget. When a user selects a place, the map zooms to that location, drops a marker, and populates the form fields using the structured data returned by Google.
Here’s what’s happening behind the scenes:
1. JavaScript Setup
On your APEX page, add the following JavaScript function in the Page Function and Global Variable Declaration section:
let map;
let marker;
let infoWindow;
let center = { lat: 44.984647, lng: -93.2811189 };
async function initMap() {
// Request needed libraries.
//@ts-ignore
const [{ Map }, { AdvancedMarkerElement }] = await Promise.all([
google.maps.importLibrary("marker"),
google.maps.importLibrary("places")
]);
// Initialize the map.
map = new google.maps.Map(document.getElementById('map'), {
center,
zoom: 12,
mapId: '4504f8b37365c3d0',
mapTypeControl: false,
gestureHandling: "greedy",
});
//@ts-ignore
const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement();
//@ts-ignore
placeAutocomplete.id = 'place-autocomplete-input';
placeAutocomplete.locationBias = center;
const card = document.getElementById('place-autocomplete-card');
//@ts-ignore
card.appendChild(placeAutocomplete);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);
// Create the marker and infowindow.
marker = new google.maps.marker.AdvancedMarkerElement({
map,
});
infoWindow = new google.maps.InfoWindow({});
// Add the gmp-placeselect listener, and display the results on the map.
//@ts-ignore
placeAutocomplete.addEventListener('gmp-select', async ({ placePrediction }) => {
const place = placePrediction.toPlace();
await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location', 'addressComponents', 'postalAddress']});
// If the place has a geometry, then present it on a map.
if (place.viewport) {
map.fitBounds(place.viewport);
}
else {
map.setCenter(place.location);
map.setZoom(12);
}
let content = '<div id="infowindow-content">' +
'<span id="place-displayname" class="title">' + place.displayName + '</span><br />' +
'<span id="place-address">' + place.formattedAddress + '</span>' +
'</div>';
apex.item('P1_NAME).setValue(place.displayName);
apex.item('P1_BILLINGSTREET').setValue(place.postalAddress.addressLines);
apex.item('P1_BILLINGCITY').setValue(place.postalAddress.locality );
apex.item('P1_BILLINGSTATE').setValue(place.postalAddress.administrativeArea);
apex.item('P1_BILLINGPOSTALCODE').setValue(place.postalAddress.postalCode);
updateInfoWindow(content, place.location);
marker.position = place.location;
});
}
// Helper function to create an info window.
function updateInfoWindow(content, center) {
infoWindow.setContent(content);
infoWindow.setPosition(center);
infoWindow.open({
map,
anchor: marker,
shouldFocus: false,
});
}
Then, under “Execute When Page Loads”, simply call:
initMap();
2. HTML Header Code
In the page’s HTML Header, include the script that loads Google Maps:
<html>
<!-- prettier-ignore -->
<script>(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(()=>d[l](f,...n))})
({key: "YOUR_GOOGLE_API_KEY", v: "weekly"});</script>
</html>
Make sure to replace “YOUR_GOOGLE_API_KEY” with your actual API key.
3. Inline CSS Code
<html>
/**
* @license
* Copyright 2025 Google LLC. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* [START maps_place_autocomplete_map] */
/*
* Always set the map height explicitly to define the size of the div element
* that contains the map.
*/
#map {
height: 100%;
}
#googautocomplete{
height: 25rem;
}
#place-autocomplete-card {
background-color: #fff;
border-radius: 5px;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
margin: 3px;
padding: 2px;
font-family: Roboto, sans-serif;
font-size: large;
font-weight: bold;
width: 80%;
}
gmp-place-autocomplete {
width: 100%;
}
#infowindow-content .title {
font-weight: bold;
}
#map #infowindow-content {
display: inline;
}
/* [END maps_place_autocomplete_map] */
</html>
APEX Layout
Add two static content regions:
Static Region: googautocomplete
<div class="place-autocomplete-card" id="place-autocomplete-card"></div> <div id="map"></div>
Static Region: Address
This region contains your form page items (:P1_NAME, :P1_BILLINGSTREET, etc.).

Google Address Autocomplete in Oracle APEX Without a Map
If you want the autocomplete functionality but don’t need the map, you can bind Google’s autocomplete widget directly to an APEX text field. This allows users to start typing in a standard form field and receive address suggestions, without introducing any external visuals into the layout.
It’s a cleaner UI and a better fit for use cases where users only need to type and select an address—no visual confirmation required. To implement this, assign the widget’s ID to an existing APEX field and skip the static map region entirely.
Challenges and Gotchas
Google’s documentation is… not great. The hardest part was figuring out how to extract structured data from nested arrays like postalAddress.addressLines. It’s doable, but it requires diving deep into their developer guides—and occasionally clicking links that land you on a page explaining what an array is.
Also, keep in mind:
- Not all places return the same data. Landmarks like Alcatraz Island or the Golden Gate Bridge may not return a full address.
- Some API changes in 2024 mean older code examples are now broken. This version reflects the updated structure.
Final Thoughts
This approach gives users a fast, intuitive way to enter accurate address data—and gives developers cleaner data in the process. Whether you use the map or just the input field, Oracle APEX Google Maps address autocomplete offers a fast, modern experience for capturing valid address data.
Have questions or want help implementing this in your own APEX environment? Contact us to get started.




