Skip to main content

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:
1

Entry Events

Triggered when a user enters a geofence.Event type: RadarEventTypeUserEnteredGeofence
func 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 ?? "")")
        }
    }
}
2

Exit Events

Triggered when a user exits a geofence.Event type: RadarEventTypeUserExitedGeofence
func 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).
3

Dwell Events

Triggered when a user dwells in a geofence for a specified duration.Event type: RadarEventTypeUserDwelledInGeofence
func 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

ParameterTypeDescription
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

1

Use Tags for Organization

Organize geofences with tags (e.g., “store”, “warehouse”, “restaurant”) for easy filtering and management.
2

Leverage Metadata

Store additional context in geofence metadata (store IDs, manager contacts, operating details) for personalization.
3

Set Appropriate Radii

Use smaller radii (50-100m) for precise locations like stores. Use larger radii (500-1000m) for neighborhoods or zones.
4

Monitor Event Confidence

Check event confidence levels and handle high-confidence events differently than low-confidence ones.
5

Enable Geofence Syncing

Enable syncGeofences for better responsiveness and reduced latency in geofence events.
For more details on geofencing, visit the Radar documentation.