# Location permission not triggered on page load without user action

- **Pattern:** `ab-001047` (`directory-map-location.location-search.permission-on-demand`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001047
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001047)

## Why it matters

Triggering a geolocation permission prompt on page load — before any user interaction — violates GDPR Art. 5(1)(b) (purpose limitation and data minimisation) and ePrivacy Art. 5(3), which require that access to device capabilities be tied to a specific, user-initiated purpose. Browsers increasingly penalize automatic permission requests by pre-denying them, meaning an auto-triggered geolocation call trains the browser to block your site permanently. Beyond compliance, an unexpected permission dialog on load is a hostile UX pattern that signals your site does not respect user agency — a trust-damaging first impression for a directory product that depends on repeat engagement.

## Severity rationale

Medium because unsolicited geolocation requests violate GDPR and ePrivacy requirements and cause browsers to pre-block your site's location access, degrading the feature for all future visits.

## Remediation

Remove any `navigator.geolocation` call from component mount effects and ensure the call is made exclusively in response to an explicit user action such as a button click.

```tsx
// WRONG — fires on mount, before any interaction
useEffect(() => {
  navigator.geolocation.getCurrentPosition(handleLocation, handleError);
}, []);

// CORRECT — fires only on explicit user click
function MapComponent() {
  const handleNearMe = () => {
    navigator.geolocation.getCurrentPosition(handleLocation, handleError);
  };
  return <button onClick={handleNearMe}>Find Near Me</button>;
}
```

Search `src/` for all `navigator.geolocation` call sites and confirm none appear inside `useEffect` with an empty dependency array or any top-level component body. Audit both the map component and any location-aware search components.

## Detection

- **ID:** `permission-on-demand`
- **Severity:** `medium`
- **What to look for:** Load the page in a fresh browser with no geolocation permission history. Check whether any permission prompt appears automatically, or only after user clicks "near me" or similar. Search the code for `navigator.geolocation.getCurrentPosition` calls in useEffect with an empty or missing dependency array.
- **Pass criteria:** No geolocation permission prompt appears on page load. Enumerate all calls to `navigator.geolocation` and confirm 0% fire on mount without user interaction. Permission is requested only after the user explicitly clicks a "near me" button or similar action.
- **Fail criteria:** Geolocation permission prompt appears automatically on page load before any user interaction. A geolocation call inside useEffect with an empty dependency array does not count as pass.
- **Skip (N/A) when:** No geolocation feature exists.
- **Detail on fail:** `"Geolocation permission prompt shown automatically on page load before user interacts with any button"` or `"navigator.geolocation called in useEffect without dependencies, requesting permission on every render"`
- **Remediation:** Only request geolocation in response to explicit user action:

  ```tsx
  function MapComponent() {
    // GOOD: Requests permission only on click
    const handleNearMe = () => {
      navigator.geolocation.getCurrentPosition(
        (pos) => { /* handle success */ },
        (err) => { /* handle error */ }
      );
    };

    return <button onClick={handleNearMe}>Find Near Me</button>;
  }
  ```

## External references

- gdpr Art. 5(1)(b)
- gdpr Art. 9
- eprivacy Art. 5(3)

Taxons: privacy-consent

HTML version: https://auditbuffet.com/patterns/ab-001047
