Overview
Radar’s geofencing capabilities allow you to create custom geofences and monitor when users enter, exit, or dwell in specific locations. Geofences can be circular or polygon-shaped and include rich metadata for targeting and personalization.
Understanding Geofences
Geofences are virtual boundaries that trigger events when a user crosses them. Each geofence includes:
Unique identifier : Radar ID and optional external ID
Tag : Categorize geofences (e.g., “store”, “warehouse”, “delivery-zone”)
Description : Human-readable name
Geometry : Circle or polygon shape
Metadata : Custom key-value pairs for additional context
Operating hours : Optional hours when the geofence is active
Geofence Events
Radar generates three types of geofence events:
Entry Events
Triggered when a user enters a geofence. Event type : RadarEventTypeUserEnteredGeofencefunc didReceiveEvents ( _ events : [RadarEvent], user : RadarUser ? ) {
for event in events {
if event.type == .userEnteredGeofence {
let geofence = event. geofence
print ( "Entered: \( geofence ? . tag ?? "" ) " )
print ( "Description: \( geofence ? . __description ?? "" ) " )
}
}
}
Exit Events
Triggered when a user exits a geofence. Event type : RadarEventTypeUserExitedGeofencefunc didReceiveEvents ( _ events : [RadarEvent], user : RadarUser ? ) {
for event in events {
if event.type == .userExitedGeofence {
let geofence = event. geofence
let duration = event. duration // in minutes
print ( "Exited: \( geofence ? . tag ?? "" ) after \( duration ) minutes" )
}
}
}
Exit events include a duration property indicating how long the user was inside the geofence (in minutes).
Dwell Events
Triggered when a user dwells in a geofence for a specified duration. Event type : RadarEventTypeUserDwelledInGeofencefunc didReceiveEvents ( _ events : [RadarEvent], user : RadarUser ? ) {
for event in events {
if event.type == .userDwelledInGeofence {
let geofence = event. geofence
print ( "Dwelled in: \( geofence ? . tag ?? "" ) " )
// Access geofence metadata
if let metadata = geofence ? .metadata {
print ( "Metadata: \( metadata ) " )
}
}
}
}
Configure dwell duration thresholds in the Radar dashboard. Default is 5 minutes.
Searching for Geofences
You can search for nearby geofences using the searchGeofences() method.
Search Near Current Location
Radar. searchGeofences { (status, location, geofences) in
if status == .success {
// geofences sorted by distance
for geofence in geofences ?? [] {
print ( "Geofence: \( geofence. __description ) " )
print ( "Tag: \( geofence. tag ?? "" ) " )
print ( "External ID: \( geofence. externalId ?? "" ) " )
}
}
}
Search with Filters
Filter geofences by tag, metadata, radius, and limit:
let location = CLLocation ( latitude : 40.7128 , longitude : -74.0060 )
let tags = [ "store" , "restaurant" ]
let metadata = [ "category" : "retail" ]
Radar. searchGeofences (
near : location,
radius : 1000 , // meters
tags : tags,
metadata : metadata,
limit : 10 ,
includeGeometry : false
) { (status, location, geofences) in
if status == .success {
print ( "Found \( geofences ? . count ?? 0 ) geofences" )
}
}
Search Parameters
Parameter Type Description nearCLLocation?Location to search near. Use nil for current location. radiusintRadius to search in meters (100-10000). Use -1 for unlimited. tags[String]?Filter by geofence tags. metadata[String: Any]?Filter by geofence metadata key-value pairs. limitintMaximum number of results (1-1000). Default is 100. includeGeometryBOOLInclude full geometry in response. Set to false for >100 results.
To retrieve more than 100 geofences, set includeGeometry to false. Including geometry data limits results to 100.
Geofence Properties
Access geofence properties from the RadarGeofence object:
let geofence: RadarGeofence = event. geofence !
// Identifiers
let radarId = geofence. _id
let externalId = geofence. externalId
let tag = geofence. tag
// Description
let description = geofence. __description
// Metadata
if let metadata = geofence.metadata {
let storeNumber = metadata[ "store_number" ] as? String
let region = metadata[ "region" ] as? String
}
// Geometry
let geometry = geofence. geometry
if let circleGeometry = geometry as? RadarCircleGeometry {
let center = circleGeometry. center
let radius = circleGeometry. radius
} else if let polygonGeometry = geometry as? RadarPolygonGeometry {
let coordinates = polygonGeometry. coordinates
}
// Operating hours
if let operatingHours = geofence.operatingHours {
// check if currently open
}
Syncing Geofences
Enable geofence syncing to download nearby geofences to the device for improved responsiveness:
let trackingOptions = RadarTrackingOptions. presetResponsive
trackingOptions. syncGeofences = true
Radar. startTracking ( trackingOptions : trackingOptions)
Enabling syncGeofences allows the SDK to monitor nearby geofences locally, reducing latency for entry and exit events.
Using Client Geofences
Client geofences create local iOS region monitoring around the user’s current location:
let trackingOptions = RadarTrackingOptions. presetResponsive
// Enable stopped geofence
trackingOptions. useStoppedGeofence = true
trackingOptions. stoppedGeofenceRadius = 100 // meters
// Enable moving geofence
trackingOptions. useMovingGeofence = true
trackingOptions. movingGeofenceRadius = 200 // meters
Radar. startTracking ( trackingOptions : trackingOptions)
Client geofences use Apple’s region monitoring service to wake the app when the user moves beyond the specified radius, improving battery efficiency.
Event Confidence
Geofence events include a confidence level indicating the likelihood that the event is accurate:
func didReceiveEvents ( _ events : [RadarEvent], user : RadarUser ? ) {
for event in events {
switch event.confidence {
case . high :
// High confidence - act immediately
print ( "High confidence event" )
case . medium :
// Medium confidence - may want to verify
print ( "Medium confidence event" )
case . low :
// Low confidence - treat with caution
print ( "Low confidence event" )
case . none :
print ( "Unknown confidence" )
@unknown default :
break
}
}
}
Verifying Events
You can accept or reject geofence events to improve accuracy:
// Accept an event
let eventId = event. _id
Radar. acceptEventId (eventId, verifiedPlaceId : nil )
// Reject an event
Radar. rejectEventId (eventId)
Event verifications help Radar’s machine learning improve future event accuracy and confidence levels.
Use Cases
Store Pickup Trigger curbside pickup notifications when customers arrive at store geofences.
Delivery Zones Monitor when delivery drivers enter and exit delivery zones for real-time tracking.
Attendance Tracking Track employee or student attendance based on geofence entry/exit events.
Marketing Campaigns Send targeted messages when users enter specific geographic areas or competitor locations.
Best Practices
Use Tags for Organization
Organize geofences with tags (e.g., “store”, “warehouse”, “restaurant”) for easy filtering and management.
Leverage Metadata
Store additional context in geofence metadata (store IDs, manager contacts, operating details) for personalization.
Set Appropriate Radii
Use smaller radii (50-100m) for precise locations like stores. Use larger radii (500-1000m) for neighborhoods or zones.
Monitor Event Confidence
Check event confidence levels and handle high-confidence events differently than low-confidence ones.
Enable Geofence Syncing
Enable syncGeofences for better responsiveness and reduced latency in geofence events.