### PREREQUISITES

In order to implement the Pilgrim SDK in your app, you must first complete the following:

- **Foursquare Developer Account w/ ClientID + Secret**
- **Pilgrim Access Enabled**

Please [Contact Us](https://foursquare.com/contact-us) if you have not signed up for access.

## 1. Register App Bundle ID

In order for Pilgrim SDK to authenticate with our server, you'll need to add your iOS Bundle ID to your Foursquare app's configuration.

1. Navigate to your [Foursquare Developer Console](https://foursquare.com/developers/apps/) and select your app, then:

2. Find your app's **Bundle Identifier**. This can be found in the **Identity** section of your project's **General** tab:

3. In your Foursquare Developer Console on the **Pilgrim SDK Settings** page, paste your iOS Bundle ID in the **iOS Bundle IDs** field.

**Note:** you can add multiple bundle IDs delimited by commas.

4. Save your changes.

## 2. Install the Pilgrim SDK

_If you are upgrading from a previous version of Pilgrim SDK that used a `.netrc` file, please take a look at [these additional steps](https://docs.foursquare.com/developer/docs/additional-resources#upgrade-from-a-previous-sdk-version) that you may need to complete._

### Option 1 - Carthage

1. Add the following to your `Cartfile`:

```text
binary "https://foursquare.jfrog.io/foursquare/pilgrimsdk-ios/Pilgrim.json" ~> 3.4.0
```

2. Navigate to **Carthage/Build/iOS** and drag the `Pilgrim.framework` file into Xcode in the **Link Binary With Libraries** section.

3. Add a run script with the following script: `/usr/local/bin/carthage copy-frameworks`

4. Set the **Input Files** to: `$(SRCROOT)/Carthage/Build/iOS/Pilgrim.framework`

5. Load the Pilgrim library into any necessary files by adding `import Pilgrim`.

6. Build your project.

### Option 2 - CocoaPods

1. If you don't already have CocoaPods initiated in your project, enter the following command into the terminal: `pod init`

2. Add the following to your **Podfile**:

```text
pod 'Pilgrim', '~> 3.4.0'
```

3. Enter the following command into the terminal: `pod install` (If you experience errors, try `pod update`. You can [read about the difference here](https://guides.cocoapods.org/using/pod-install-vs-update.html).)

4. Load the Pilgrim library into any necessary files by adding `import Pilgrim`.

5. Build your project.

### Option 3 - Swift Package Manager

1. In Xcode, install the Pilgrim SDK by navigating to **File > Add Packages…**
2. In the prompt that appears, search for the Pilgrim SDK with the following Package URL: `https://github.com/foursquare/pilgrim-ios-spm.git`
3. Select the version of Pilgrim you want to use. For new projects, we recommend using the newest version of Pilgrim.

### Option 4 - Manual

1. [Download and unzip the latest release.](https://foursquare.jfrog.io/foursquare/pilgrimsdk-ios/v3.0.1/Pilgrim.framework.zip)

2. Embed the framework. Drag `Pilgrim.framework` into your project's **Embedded Binaries** section in the project editor. In the sheet that appears, make sure "Copy items if needed" is checked, then click **Finish**.

3. Load the Pilgrim library into any necessary files by adding `import Pilgrim`.

4. Under the **Build Phases** tab, add this run script (for manual installs only):

```text
bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Pilgrim.framework/strip-frameworks.sh"
```

5. Build your project.

## 3. Configure the Pilgrim SDK

### a. Configure Permissions

1. Turn **Background Modes** to **On** in your project's **Capabilities** tab and enable the **Location updates** checkbox:

2. Add the following to your iOS permission strings in your project's **Info.plist** file:
   - Privacy - Location Always Usage Description
   - Privacy - Location Always and When In Use Usage Description
   - Privacy - Location When In Use Usage Description

### b. Configure your AppDelegate

Configure Pilgrim by pasting the following code in the **didFinishLaunchingWithOptions** method of your **AppDelegate**. Be sure to replace `CLIENT_ID` and `CLIENT_SECRET` with your real API credentials.

```swift
PilgrimManager.shared().configure(withConsumerKey: "CLIENT_ID", secret: "CLIENT_SECRET", delegate: self, completion: nil)
```

### c. Disable AdId transmission

If you're using the free tier or do not have a data sharing agreement, you don't need to transmit the phone's mobile AdId to Foursquare. While we currently just disregard the AdId in these cases as soon as it is received, Pilgrim 2.2.2+ gives you the ability to disable the device from even sending it to Foursquare by setting the following:

```swift
# before the configure call:
PilgrimManager.shared().disableAdIdentitySharing = true
```

### d. Conform to Pilgrim Delegate

Have your **AppDelegate** conform `PilgrimManagerDelegate` by pasting the following code just below your AppDelegate class:

```swift
extension AppDelegate : PilgrimManagerDelegate {
  // Primary visit handler:
  func pilgrimManager(_ pilgrimManager: PilgrimManager, handle visit: Visit) {
    // Process the visit however you'd like:
    print("[33m\(visit.hasDeparted ? \"Departure from\" : \"Arrival at\") \(visit.venue != nil ? visit.venue!.name : \"Unknown venue.\"). Added a Pilgrim visit at: \(visit.displayName)\")
  }

// Optional: If visit occurred without network connectivity
  func pilgrimManager(_ pilgrimManager: PilgrimManager, handleBackfill visit: Pilgrim.Visit) {
    // Process the visit however you'd like:
    print("[33mBackfill \(visit.hasDeparted ? \"departure from\" : \"arrival at\") \(visit.venue != nil ? visit.venue!.name : \"Unknown venue.\"). Added a Pilgrim backfill visit at: \(visit.displayName)\")
  }

// Optional: If visit occurred by triggering a geofence
  func pilgrimManager(_ pilgrimManager: PilgrimManager, handle geofenceEvents: [GeofenceEvent]) {
    // Process the geofence events however you'd like. Here we loop through the potentially multiple geofence events and handle them individually:
    geofenceEvents.forEach { geofenceEvent in
      print(geofenceEvent)
    }
  }

// Optional: If there is an update to the user state
  func pilgrimManager(_ pilgrimManager: PilgrimManager, handleUserState updatedUserState: UserState, changedComponents: UserStateComponent) {
    switch changedComponents {
    case .city:
      print("Welcome to \(updatedUserState.city)")
      // handle other cases
    }
  }

// Optional: If there is an error
    func pilgrimManager(_ pilgrimManager: PilgrimManager, handle error: Error) {
      // handle any Pilgrim errors
      print(error)
    }
}
```

## 4. Initialize Pilgrim

Once Pilgrim is configured and set up to handle location events, you need to [request location permissions](https://developer.apple.com/documentation/corelocation/requesting_authorization_for_location_services) from your user and tell Pilgrim to start running by calling `start` when `.authorizedAlways`:

```swift
PilgrimManager.shared().start()
```

**Note:** You must make sure the user has provided access to background location permissions before starting the SDK. It is your responsibility as a developer to inform the user of how you are using these permissions and how it benefits them.

### a. Request Foreground Location

Pilgrim's traditional visit detection works effortlessly in the background, allowing continued interaction with your users regardless of if they are in your app or not. But what about when you want to manually find a user's current location while they are interacting within your app? Pilgrim allows you to actively request the device's current location manually when the app is in use by calling the below method:

```swift
PilgrimManager.shared().getCurrentLocation { (currentLocation, error) in
   // Example: currentLocation.currentPlace.venue.name
}
```

```objectivec
[[FSQPPilgrimManager sharedManager] getCurrentLocationWithCompletion:^(FSQPCurrentLocation * _Nullable currentLocation, NSError * _Nullable error) {
   // Example: currentLocation.currentPlace.venue.name
}];
```

## Optional Configurations

### Adding Wifi Entitlement

As of iOS 13.0 in order for Pilgrim to collect Wifi Scans the app must be configured to access Wifi information via the Wifi Entitlement. This optional step involves editing the app configuration, regenerating provisioning profiles, and updating the app in Xcode.

#### 1. Editing the app configuration

Go to the [Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources) portal on the Apple Developer site, then click on Identifiers, then select the app identifier you want to add the Wifi Entitlement to. In the Capabilities section enable to Access WiFi Information capability and click Save. A warning will be displayed about regenerating the provisioning profiles, click Confirm, we will regenrate them in the next step.

#### 2. Regenerate provisioning profiles

Still on the Certificates, Identifiers & Profiles portal, click on Profiles to list the provisioning profiles, you will need to regenerate any profile that was created for the app identifier updated in the previous step (the profile should have an expiration date of 'Invalid'). Select the profile and click the Edit button, then click Save. In the profile list the expiration date should no longer be 'Invalid'

#### 3. Update the app in Xcode

In Xcode, open the preferences pane (Xcode > Preferences) then select Accounts. Select your Apple ID and team, then click Download Manual Profiles. In the Project Navigator select the Xcode project file (.xcodeproj) and go to the Signing and Capabilities pane. Select the `+ Capability` button and double click on `Access Wifi Information`. This will add the `com.apple.developer.networking.wifi-info` key to your Entitlements plist file. In the signing configurations if you see an error saying the provisioning profile does not include the `com.apple.developer.networking.wifi-info` entitlement, then you need to redownload the provisioning profiles again through Xcode or manually using the Developer portal.
