API key and billing
- Create a key in Google Cloud, enable Maps JavaScript API.
- Enable billing.
- Restrict to your site’s HTTP referrers.
Minimal implementation
<div id="map" style="width:100%;height:400px"></div>
<script defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&callback=initMap"></script>
<script>
function initMap(){
const center={lat:37.422,lng:-122.084};
const map=new google.maps.Map(document.getElementById('map'),{center,zoom:15});
new google.maps.Marker({position:center,map,title:'Acme HQ'});
}
</script>
Markers and info windows
Add a single marker first. For multiple locations, consider marker clustering to keep performance predictable.
Performance considerations
- Defer the API and initialize on intersection (when scrolled into view).
- Only load libraries you need.
- Keep DOM lightweight; avoid heavy overlays.
Troubleshooting
- RefererNotAllowedMapError: check referrer patterns (include subdomains and protocols).
- Watermark "For development purposes only": verify billing.
- Gray tiles: verify network and quota; try directly loading the API URL.
Prefer a simple embed?
Use the iframe method for a single static location. See: Embed a Google Map on Your Website.
Load on demand (IntersectionObserver)
Delay loading until the map scrolls into view:
<div id="map" style="width:100%;height:400px"></div>
<script>
const el=document.getElementById("map");
const load=()=>{const s=document.createElement("script");s.src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&callback=initMap";s.defer=true;document.head.appendChild(s)};
new IntersectionObserver((e,o)=>{if(e[0].isIntersecting){load();o.disconnect()}},{rootMargin:"200px"}).observe(el);
function initMap(){const c={lat:37.422,lng:-122.084};const m=new google.maps.Map(el,{center:c,zoom:15});new google.maps.Marker({position:c,map:m})}
</script>
Custom styles and mapId
Use a mapId
(from Google Cloud) for styled maps and vector features. Pass { mapId: "YOUR_MAP_ID" }
in the map options.
Multiple locations (clustering)
For many points, use the official MarkerClusterer library to bundle nearby markers and reduce DOM work.
Accessibility
- Provide nearby text equivalents (address, directions) and an "Open in Google Maps" link.
- Ensure focus order remains logical; set
tabindex="-1"
on the map container if needed to avoid trapping focus.
Frequently Asked Questions
Why do I see quota or billing errors?
The JS API requires billing even for small usage. Ensure billing is enabled and quotas are sufficient.
How do I secure my API key?
Restrict HTTP referrers to your domains, rotate keys periodically, and avoid exposing admin‑only keys in client code.