Skip to content

Geofence

export interface Geofence {

A geofence definition for monitoring circular or polygon regions.

The SDK implements the native iOS and Android Geofencing APIs, extended with polygon support and a proximity-based infinite-geofencing system that overcomes the platform limits of 20 (iOS) and 100 (Android) simultaneous geofences.

Contents

Overview
Field Required Description
identifier Unique name for this geofence.
latitude ✅* Center latitude (*omit for polygon geofences).
longitude ✅* Center longitude (*omit for polygon geofences).
radius ✅* Radius in meters (*omit for polygon geofences).
notifyOnEntry Fire event on entry.
notifyOnExit Fire event on exit.
notifyOnDwell Fire event after loitering for loiteringDelay ms.
vertices Polygon geofence vertices (replaces lat/lng/radius).
extras Arbitrary key-value metadata posted with each event.

Warning

Both platforms require GeoConfig.locationAuthorizationRequest to be "Always". Geofencing does not work with "WhenInUse" only.


Adding geofences

Use BackgroundGeolocation.addGeofence for a single geofence, or BackgroundGeolocation.addGeofences for bulk inserts (approximately 10× faster than inserting individually).

If a geofence with the same identifier already exists in the database, it is replaced.

BackgroundGeolocation.addGeofence({
  identifier: "Home",
  radius: 200,
  latitude: 45.51921926,
  longitude: -73.61678581,
  notifyOnEntry: true,
  notifyOnExit: true,
  extras: { route_id: 1234 }
});
await BackgroundGeolocation.addGeofences([{
  identifier: "Home",
  radius: 200,
  latitude: 45.51921926,
  longitude: -73.61678581,
  notifyOnEntry: true,
}, {
  identifier: "Work",
  radius: 200,
  latitude: 45.61921927,
  longitude: -73.71678582,
  notifyOnEntry: true
}]);

Listening for events

Subscribe to geofence transitions with BackgroundGeolocation.onGeofence. Subscribe to changes in the actively monitored set with BackgroundGeolocation.onGeofencesChange.

BackgroundGeolocation.onGeofence((event) => {
  console.log("[onGeofence]", event.identifier, event.action);
});

BackgroundGeolocation.onGeofencesChange((event) => {
  const on = event.on;   // newly activated geofences
  const off = event.off; // deactivated geofence identifiers

  on.forEach((geofence) => createGeofenceMarker(geofence));
  off.forEach((identifier) => removeGeofenceMarker(identifier));
});

Note

When all geofences are removed, BackgroundGeolocation.onGeofencesChange fires with empty arrays for both on and off.


Polygon geofencing

The SDK supports polygon geofences of any shape via the vertices field. Polygon geofencing is sold as a separate add-on but is fully functional in DEBUG builds.

When defining a polygon geofence, omit latitude, longitude, and radius — the SDK calculates the minimum enclosing circle automatically from the polygon geometry.

BackgroundGeolocation.addGeofence({
  identifier: "Park",
  notifyOnEntry: true,
  notifyOnExit: true,
  vertices: [
    [45.518947279987714, -73.6049889209514],
    [45.5182711292279,   -73.60338649600598],
    [45.517082240237634, -73.60432670908212],
    [45.51774871402813,  -73.60604928622278]
  ]
});

Infinite geofencing

The SDK stores all geofences in its database and uses a geospatial query to activate only the nearest geofences within GeoConfig.geofenceProximityRadius, staying within the platform limit. As the device moves, the active set is periodically refreshed.

  • The minimum GeoConfig.geofenceProximityRadius is enforced at 1000 meters.
  • Geofences within the radius (green in the diagram below) are actively monitored.
  • Geofences outside the radius (grey) remain in the database but are dormant.


Removing geofences

Geofences persist in the SDK's database until explicitly removed. If AppConfig.stopOnTerminate is false and AppConfig.startOnBoot is true, geofences continue to be monitored across app termination and device reboots.

await BackgroundGeolocation.removeGeofence("Home");
await BackgroundGeolocation.removeGeofences();
const geofences = await BackgroundGeolocation.getGeofences();
console.log("[getGeofences]", geofences);

Geofences-only mode

Call BackgroundGeolocation.startGeofences instead of BackgroundGeolocation.start to monitor geofences without continuous location tracking. Use GeoConfig.geofenceModeHighAccuracy to improve event responsiveness at the cost of higher power usage.

The SDK can switch between full tracking and geofences-only mode at any time by calling the corresponding start method.

BackgroundGeolocation.onGeofence((event) => {
  console.log("[onGeofence]", event);
});

await BackgroundGeolocation.ready({
  http: { url: "https://your.server.com/geofences", autoSync: true },
  geolocation: { geofenceModeHighAccuracy: true }
});
BackgroundGeolocation.startGeofences();

Examples
BackgroundGeolocation.onGeofence((event) => {
  if (event.identifier === "DANGER_ZONE") {
    if (event.action === "ENTER") {
      // Entering the zone — switch to full location tracking.
      BackgroundGeolocation.start();
    } else if (event.action === "EXIT") {
      // Exiting the zone — return to geofences-only mode.
      BackgroundGeolocation.startGeofences();
    }
  }
});

BackgroundGeolocation.addGeofence({
  identifier: "DANGER_ZONE",
  radius: 1000,
  latitude: 45.51921926,
  longitude: -73.61678581,
  notifyOnEntry: true,
  notifyOnExit: true,
});

await BackgroundGeolocation.ready({
  geolocation: {
    desiredAccuracy: BackgroundGeolocation.DesiredAccuracy.High,
    distanceFilter: 10,
  },
  http: { url: "https://your.server.com/locations", autoSync: true }
});
BackgroundGeolocation.startGeofences();
Single geofence
BackgroundGeolocation.addGeofence({
  identifier: "Home",
  radius: 200,
  latitude: 45.51921926,
  longitude: -73.61678581,
  notifyOnEntry: true,
  notifyOnExit: true,
  extras: { route_id: 1234 }
});
Multiple geofences
await BackgroundGeolocation.addGeofences([{
  identifier: "Home",
  radius: 200,
  latitude: 45.51921926,
  longitude: -73.61678581,
  notifyOnEntry: true,
}, {
  identifier: "Work",
  radius: 200,
  latitude: 45.61921927,
  longitude: -73.71678582,
  notifyOnEntry: true
}]);
Polygon geofence
BackgroundGeolocation.addGeofence({
  identifier: "Park",
  notifyOnEntry: true,
  notifyOnExit: true,
  vertices: [
    [45.518947279987714, -73.6049889209514],
    [45.5182711292279,   -73.60338649600598],
    [45.517082240237634, -73.60432670908212],
    [45.51774871402813,  -73.60604928622278]
  ]
});
Remove a single geofence
await BackgroundGeolocation.removeGeofence("Home");
Remove all geofences
await BackgroundGeolocation.removeGeofences();
Fetch all stored geofences
const geofences = await BackgroundGeolocation.getGeofences();
console.log("[getGeofences]", geofences);
Geofences-only mode
BackgroundGeolocation.onGeofence((event) => {
  console.log("[onGeofence]", event);
});

await BackgroundGeolocation.ready({
  http: { url: "https://your.server.com/geofences", autoSync: true },
  geolocation: { geofenceModeHighAccuracy: true }
});
BackgroundGeolocation.startGeofences();
Toggle between location tracking and geofences-only mode
BackgroundGeolocation.onGeofence((event) => {
  if (event.identifier === "DANGER_ZONE") {
    if (event.action === "ENTER") {
      // Entering the zone — switch to full location tracking.
      BackgroundGeolocation.start();
    } else if (event.action === "EXIT") {
      // Exiting the zone — return to geofences-only mode.
      BackgroundGeolocation.startGeofences();
    }
  }
});

BackgroundGeolocation.addGeofence({
  identifier: "DANGER_ZONE",
  radius: 1000,
  latitude: 45.51921926,
  longitude: -73.61678581,
  notifyOnEntry: true,
  notifyOnExit: true,
});

await BackgroundGeolocation.ready({
  geolocation: {
    desiredAccuracy: BackgroundGeolocation.DesiredAccuracy.High,
    distanceFilter: 10,
  },
  http: { url: "https://your.server.com/locations", autoSync: true }
});
BackgroundGeolocation.startGeofences();

Members

entryState

entryState?: number;

Current entry state of the geofence.

Value State
0 Outside
1 Inside

extras

extras?: Record<string, unknown>;

Arbitrary key-value metadata attached to each geofence event and included in the payload posted to HttpConfig.url.

hits

hits?: number;

Number of times this geofence has been triggered since it was added.

identifier

identifier: string;

Unique identifier for this geofence.

Used to reference the geofence in events and removal calls. Adding a geofence with an identifier that already exists replaces the existing one.

latitude

latitude: number;

Latitude of the circular geofence center.

Omit when defining a polygon geofence via vertices — the SDK calculates the center automatically.

loiteringDelay

loiteringDelay?: number;

Minimum time in milliseconds the device must remain inside the geofence before a notifyOnDwell event fires. Default 0.

longitude

longitude: number;

Longitude of the circular geofence center.

Omit when defining a polygon geofence via vertices — the SDK calculates the center automatically.

notifyOnDwell

notifyOnDwell?: boolean;

Fire a GeofenceEvent when the device has remained inside this geofence for loiteringDelay milliseconds.

notifyOnEntry

notifyOnEntry?: boolean;

Fire a GeofenceEvent when the device enters this geofence.

See also - GeoConfig.geofenceInitialTriggerEntry

notifyOnExit

notifyOnExit?: boolean;

Fire a GeofenceEvent when the device exits this geofence.

radius

radius: number;

Radius of the circular geofence in meters.

Omit when defining a polygon geofence via vertices — the SDK calculates the enclosing radius automatically.

Warning

The minimum reliable radius is 200 meters. Below this threshold, geofences may not trigger reliably on either platform.

Apple documents this explicitly:

"For testing purposes, you can assume that the minimum distance is approximately 200 meters."

stateUpdatedAt

stateUpdatedAt?: number;

Epoch timestamp in seconds of the last geofence transition.

vertices

vertices?:Vertices;

Polygon geofence vertices as [[lat, lng], ...] pairs.

When provided, the geofence is treated as a polygon rather than a circle. Omit latitude, longitude, and radius — the SDK solves the minimum enclosing circle from the vertex geometry and registers that as the native circular geofence.

When the device enters the enclosing circle, the SDK begins C++ hit-testing against the polygon at high frequency. When it exits the circle, polygon monitoring ceases.

Note

Polygon geofencing is sold as a separate add-on but is fully functional in DEBUG builds.

BackgroundGeolocation.addGeofence({
  identifier: "Home",
  notifyOnEntry: true,
  notifyOnExit: true,
  vertices: [
    [45.518947279987714, -73.6049889209514],
    [45.5182711292279,   -73.60338649600598],
    [45.517082240237634, -73.60432670908212],
    [45.51774871402813,  -73.60604928622278]
  ]
});