Skip to Content
DevelopersSDKsiOS SDKGeofencing & location

Geofencing & location

The ActiveReachLocation companion product wraps CoreLocation so you can monitor outlet geofences and emit geofence.entered / geofence.exited events when a customer walks into or out of one of your stores. It handles the iOS per-app region limit transparently and is battery-light by design (significant-location-change re-evaluation, ~100m default radius).

The Swift class is AegisLocation, exposed through the runtime as Aegis.shared.location.

Geofencing is strictly opt-in. It does not auto-activate. The SDK never requests location permission on your behalf and nothing prompts the user unless you explicitly enable it with AegisConfig.enableLocation AND call startMonitoring(...). enableLocation defaults to false. CoreLocation only prompts after you, the host app, request authorization yourself.

Enabling location

Geofencing only activates when two things are true: you opt in via AegisConfig.enableLocation, and you call startMonitoring(...). Until both happen, no CoreLocation machinery runs and nothing prompts the user.

import ActiveReachSDK Aegis.shared.initialize( writeKey: "YOUR_WRITE_KEY", config: AegisConfig( workspaceId: "YOUR_WORKSPACE_ID", enableLocation: true ) )

Permission prerequisites

The SDK does not request location permission for you — you must do it explicitly from the host app, and you must declare the usage strings in Info.plist. Without these, CoreLocation will refuse to monitor regions.

Add the appropriate usage description keys to your app’s Info.plist:

  • NSLocationWhenInUseUsageDescription — required for foreground-only monitoring.
  • NSLocationAlwaysAndWhenInUseUsageDescription — required if you want geofences to fire while the app is backgrounded.

Then request authorization yourself, choosing the level your app needs:

import CoreLocation let manager = CLLocationManager() // Foreground-only fires (geofences only while the app is in use): manager.requestWhenInUseAuthorization() // Background fires (geofences fire even when the app is backgrounded): manager.requestAlwaysAuthorization()

.authorizedAlways is required for region monitoring to fire in the background. .authorizedWhenInUse works only while the app is in the foreground. The SDK monitors with whichever level you have granted — it never forces Always.

Configuring geofences

Build a Geofence per outlet and pass the full set to startMonitoring(geofences:). The radiusMeters defaults to 100. Use metadata to carry per-outlet attributes that you want stamped onto the enter/exit events.

import ActiveReachLocation let geofences = [ AegisLocation.Geofence( id: "outlet_bandra", label: "Bandra", latitude: 19.0596, longitude: 72.8295, radiusMeters: 120, metadata: ["outlet_code": "MUM-BDR"] ), AegisLocation.Geofence( id: "outlet_andheri", label: "Andheri", latitude: 19.1136, longitude: 72.8697 // radiusMeters defaults to 100 ) ] Aegis.shared.location.startMonitoring(geofences: geofences)

To stop monitoring entirely (for example on user opt-out), call:

Aegis.shared.location.stopMonitoring()

This stops all region monitoring and significant-location-change updates and clears the configured set.

The 20-region cap is handled for you

iOS imposes a hard limit of 20 simultaneously-monitored regions per app. You don’t have to manage this — configure all your outlets, and the SDK monitors the nearest 20 to the device, automatically re-sorting as the customer moves.

It does this via significant-location-change updates (~500m granularity, battery-light): each update re-sorts the configured geofences by distance from the device and swaps in the closest 20. Walking toward your 21st outlet still fires entry because the SLC update brings it into the monitored set before you arrive.

In short: configure every outlet you have; the SDK picks the nearest 20 at any moment.

Reacting to enter / exit events

When a customer crosses a geofence boundary, the SDK emits canonical events through its standard track() path:

  • geofence.entered
  • geofence.exited

Each event carries the geofence’s identifying properties plus any metadata you attached:

PropertySource
geofence_idGeofence.id
geofence_labelGeofence.label
geofence_latitudeGeofence.latitude
geofence_longitudeGeofence.longitude
geofence_radius_metersGeofence.radiusMeters
geofence_meta_<key>each entry in Geofence.metadata

Because these are standard tracked events, they flow into the same ingestion pipeline as the rest of your telemetry — you can use them to trigger journeys (a “welcome back” message on entry), build foot-traffic segments, or attribute visits to outlets.

If you need to react in-app to the raw events, wire your own emitter via setEmitter(_:):

Aegis.shared.location.setEmitter { eventName, properties in // eventName is "geofence.entered" or "geofence.exited" Aegis.shared.track(eventName, properties: properties) }

What’s next