Requesting location permission the moment someone lands on your page is the fastest way to get denied. Users don't trust sites that ask for sensitive permissions without context.
Your JavaScript calls navigator.geolocation.getCurrentPosition() or navigator.geolocation.watchPosition() during page load - before the user has done anything that suggests they want location features. The browser shows a permission prompt immediately, the user reflexively clicks "Block," and now your location features are permanently broken for that visitor.
Lighthouse flags this because it's both bad UX and counterproductive. Studies show permission grant rates drop significantly when prompts appear without context.
Lighthouse reports the source location in the audit details. You can also find it manually:
Cmd/Ctrl+Shift+F) for geolocationgetCurrentPosition or watchPosition// Bad: Runs on script load
navigator.geolocation.getCurrentPosition((pos) => {
console.log(pos.coords)
})
// Bad: Runs immediately when module loads
const position = await new Promise((resolve) => {
navigator.geolocation.getCurrentPosition(resolve)
})
// Bad: Inside DOMContentLoaded or load event
window.addEventListener('load', () => {
navigator.geolocation.getCurrentPosition(handlePosition)
})
Move geolocation requests inside user-triggered event handlers:
Before (bad):
// Runs on page load
navigator.geolocation.getCurrentPosition(
position => showNearbyStores(position.coords),
error => console.error(error)
)
After (good):
document.querySelector('#find-stores-btn').addEventListener('click', () => {
navigator.geolocation.getCurrentPosition(
position => showNearbyStores(position.coords),
error => showLocationError(error)
)
})
The user clicks "Find stores near me," the prompt appears, and they understand why you're asking.
For better UX, explain before the browser prompt appears:
const locationBtn = document.querySelector('#use-location')
locationBtn.addEventListener('click', async () => {
// Check current permission state
const permission = await navigator.permissions.query({ name: 'geolocation' })
if (permission.state === 'granted') {
// Already have permission, proceed
getLocation()
}
else if (permission.state === 'prompt') {
// Show custom UI explaining why
showLocationExplainer()
}
else {
// Denied - show alternative
showManualLocationInput()
}
})
function showLocationExplainer() {
const modal = document.querySelector('#location-explainer')
modal.showModal()
modal.querySelector('#confirm-location').addEventListener('click', () => {
modal.close()
getLocation()
}, { once: true })
}
function getLocation() {
navigator.geolocation.getCurrentPosition(
position => handleSuccess(position.coords),
error => handleError(error)
)
}
Always have a non-location path:
function initStoreLocator() {
// Default: show all stores or ask for zip code
showAllStores()
// Enhance with location button
const locationBtn = document.querySelector('#use-my-location')
locationBtn.addEventListener('click', requestLocation)
}
function requestLocation() {
navigator.geolocation.getCurrentPosition(
pos => filterStoresByProximity(pos.coords),
() => showZipCodeInput() // Fallback on denial/error
)
}
Run Lighthouse again - the "Requests the geolocation permission on page load" audit should pass.
setTimeout(() => { geolocation... }, 5000) is still automatic. Lighthouse may not catch it, but users will still see an unexplained prompt.navigator.permissions.query() followed by an automatic request is wrong. The permission check is fine; the automatic request isn't.Location requests might be buried in a script that only loads on certain pages. Unlighthouse scans every page on your site and flags any that trigger geolocation requests on load.