The Pilgrim SDK also offers features which you can use to augment your in-app experience, bringing location to the forefront to offer more compelling interactions to your users.

## Journeys

Pilgrim Journeys allows partners to build powerful, location-aware experiences. You can use Journeys to power in-store & curbside pickup, delivery tracking, location-based marketing, and more.

When a user is ready to embark on a journey (i.e. they tap on "I'm on my way"), Journeys will start monitoring for their arrival, provide live ETAs throughout the way, and automatically detect when a user has arrived at their destination.

### Requirements

- **Pilgrim SDK v3.1.0+**  
- **Background Location & Precise Location Enabled**

### Required AppDelegate Method

Include the following delegate methods to track journey state/eta/etc. Foursquare will return one of the following journey states:

- **In Progress**: The journey has started successfully and will now send regular updates.
- **Approaching**: The user is now approaching the destination.
- **Arrived**: The user has arrived at the destination.
- **Completed**: The journey has been completed. This is a user-generated action.
- **Canceled**: The journey has been canceled. This is a user-generated action.

```swift
protocol PilgrimManagerDelegate {
    …
    fun pilgrimManager(_ pilgrimManager: PilgrimManager, handleJourneyUpdate journey: Journey)
    …
}
```

### Available Methods

Include the following methods to ensure the correct Journeys behaviors are tracked.

- Start Journey
- Get Current Journey
- Cancel Journey
- Checkin Journey
- Complete Journey

```swift
// method
PilgrimManager.sharedManager.start(destinationId: String, destinationType: JourneyDestinationType)
// usage
PilgrimManager.sharedManager.startJourney(destinationId: venueId, destinationType: .venue, metadata: nil) { error in
    guard error == nil else {
        // handle error
        return
    }
}
```

```swift
// method
func PilgrimManager.currentJourney() -> Journey?
// usage
if let journey = PilgrimManager.sharedManager.currentJourney() {
    // do something with journey
}
```

```swift
// method
func PilgrimManager.cancelJourney(completion: ((Error?) -> Void)? = nil)
// usage
PilgrimManager.sharedManager.cancelJourney { error in
    guard error == nil else {
        // handle error
        return
    }
}
```

```swift
// method
func PilgrimManager.checkinJourney(completion: ((Error?) -> Void)? = nil)
// usage
PilgrimManager.sharedManager.checkinJourney { error in
    guard error == nil else {
        // handle error
        return
    }
}
```

```swift
// method
func PilgrimManager.completeJourney(completion: ((Error?) -> Void)? = nil)
// usage
PilgrimManager.sharedManager.completeJourney { error in
    guard error == nil else {
        // handle error
        return
    }
}
```

### Error Handling

Using the delegate method:

```swift
protocol PilgrimManagerDelegate {
    …
    fun pilgrimManager(_ pilgrimManager: PilgrimManager, handleError error: Error)
    …
}

extension FoursquarePilgrimService: PilgrimManagerDelegate {
    …
    func pilgrimManager(_ pilgrimManager: PilgrimManager, handleErrror error: Error){
        // handle error
    }
}
```

## Get Current Location

Current Location is the most comprehensive of the in-app features, allowing you to get precise place information for any user who has given your app permission to use location.

Using **Current Location** you can:

### Get Current Place

Get the same place name, category, and chain information you would receive in the background callbacks in real time in your app.

```swift
PilgrimManager.shared().getCurrentLocation { (currentLocation, error) in
   currentLocation.currentPlace
}
```

### Get Matched Geofences

If you utilize the explicit geofence functionality of Pilgrim, **Current Location** will return any Geofence Events.

```swift
PilgrimManager.shared().getCurrentLocation { (currentLocation, error) in
   currentLocation.matchedGeofences
}
```

### Get Last Known User State

The general location context information delivered through Pilgrim’s User States features return **city**, **state**, **zip** and **country** level information for all users, in addition to **home**, **work**, **traveling**, **commuting** for users who have enabled always on location.

You can access User State in one of two ways:

- Subscribing to changes via the PilgrimManager delegate

```swift
func pilgrimManager(_ pilgrimManager: PilgrimManager, handleUserState updatedUserState: UserState, changedComponents: UserStateComponent) {
    switch changedComponents {
    case .city:
      print("Welcome to \(updatedUserState.city)")
    }
}
```

- Accessing via the **PilgrimManager** Instance

```swift
PilgrimManager.shared().lastKnownUserState()
```

## Receive Geofence Events

The Pilgrim SDK v2.0+ allows geofencing around a configurable set of venues or points.

### Why Use Geofences

For use cases that rely on accuracy, regular Pilgrim SDK place visit detection is superior to geofencing. However, there are certain instances where geofencing is preferable:

- When speed and proximity to a specific _subset_ of venues is more important than accurately detecting visits there.
- When it’s more important to know if a user is _nearby_ a certain place rather than visiting.

### Event Types

Geofences have five potential event types that are delivered directly to the client and through an optional webhook:

| Event Type | Description |
| ----------- | ----------- |
| entrance | Triggered on the first GPS signal that is received inside of the geofence. |
| dwell | Triggered after the user has "dwelled" within the geofence for a configurable length of time. Default is 1 minute. |
| venue confirmed | Triggered when the device has dwelled inside a geofence radius and confirmed a stop at the venue within the radius. Only available in SDK versions 2.1.2 or greater |
| exit | Triggered on the first GPS signal that is received outside of the geofence. |
| presence | Triggered when the device is in a geofence radius during a get location request. Only available in SDK versions 2.1 or greater |

### Receiving Events

To receive geofence events on the client, add the event handler below:

```swift
// In your implementation of the pilgrim delegate, add:
func pilgrimManager(_ pilgrimManager: PilgrimManager, handle geofenceEvents: [GeofenceEvent]) {
    // Code to handle geofenceEvents...
}
```

A geofence event will contain certain fields such as:

| Field | Description |
| --- | --- |
| eventType | `entrance`, `dwell`, `venueConfirmed`, `exit`, or `presence`. |
| venue | Same as regular pilgrim venue object. |
| timestamp | Unix/epoch timestamp in milliseconds of when the event occured. |

## Provide Visit Feedback

One of the best ways to help us improve the accuracy of the Pilgrim SDK and where we think devices are located is by providing feedback about a user's visit. The more feedback we get, the smarter, faster and more accurate visits from the Pilgrim SDK become.

### Confirm and Deny a Visit

You can easily confirm whether a visit is accurate or not (and why). All you need is the `pilgrimVisitId` from the original visit.

```swift
PilgrimManager.shared().feedbackProvider.leaveVisitFeedback(feedback: FeedbackProvider.VisitFeedback, visitId: String, actualVenueId: String?, completion: ((Error?) -> Void)
```

**The available feedback options are:**

| Feedback | Description |
| --- | --- |
| VisitFeedback.confirm | The visit was at the correct venue. |
| VisitFeedback.falseStop | The user did not stop anywhere. If you are unsure, use `deny` |
| VisitFeedback.wrongVenue | The wrong venue was detected. |
| VisitFeedback.deny | Generic feedback that something was incorrect. |

### Check-in at a FSQ Venue

If you know a device is at a specific Foursquare venue, irrespective of receiving a Pilgrim Visit, you can also inform Pilgrim by providing the Foursquare venue ID:

```swift
PilgrimManager.shared().feedbackProvider?.checkIn(venueId: String)
```

### Check-in at a Partner Venue

For partners that have already harmonized their venues with Foursquare, irrespective of receiving a Pilgrim Visit, you can also inform Pilgrim that a device is at a venue by providing the partner's harmonized venue ID:

```swift
PilgrimManager.shared().feedbackProvider?.checkIn(partnerVenueId: String)
```
