Home and Work Detection

After 3-7 days of use the SDK will determine the user’s home and work location. You can see if this has been set by checking the hasHomeOrWork property.


Important: It’s possible that you won’t want to process any visits or only trust visits that have a ‘High’ confidence until home/work has been set. This is due to the fact that a user’s home is not in our venue database, so we may be attributing ‘home’ visits to a venue nearby until we learn that this is in fact their home. An example of this simple check on iOS is below:

func fsqpPilgrimManager(_ locationManager: FSQPPilgrimManager, didVisit visit: FSQPVisit) {
    if FSQPPilgrimManager.shared().hasHomeOrWork() {

        // Home and work are set. Lets print them out

    } else if visit.confidence != .high {
        // Home and work aren't set and visit confidence isn't High
        // Depending on my application I might not want to trust this visit

Other Possible Venues

To enable a list of “other venues” to be populated in your arrival events, there is a checkbox on the Pilgrim Console that you can turn on to began to receiving these venues. The venues are alternate places the device may be in order of confidence.

You can access the other places as follows:

func fsqpPilgrimManager(_ locationManager: FSQPPilgrimManager, didVisit visit: FSQPVisit) {
    let otherVenues = visit.otherPossibleVenues
    // Do something with the alternate venues
protected static final PilgrimNotificationHandler pilgrimNotificationHandler = new PilgrimNotificationHandler() {
    public void handlePlaceNotification(Context context, PilgrimSdkPlaceNotification notif) {
        CurrentPlace currentPlace = notif.getCurrentPlace();
        List\<Venue> otherVenues = currentPlace.getOtherPossibleVenues();
        // Do something with the alternate venues

Nearby Venues

You can configure proximity based nearby notifications at a global and user level. For global settings (one’s that apply to all of your users), you can configure those in the Pilgrim console on your developer site. You can read more about configuring global nearby triggers here.

User specific triggers might be useful if you have a specific piece of content that the user requested to be notified about (e.g “Remind me when I’m near the grocery store to get some candy”). You will set a list of NearbyTrigger on the Pilgrim SDK and those will be used on any subsequent stops to check for a match. These can be set and updated at any time.

To set nearby triggers on an individual device:

        var triggers = [FSQPNearbyTrigger]()
        triggers.append(FSQPNearbyTrigger(triggerType: .venue, fsqId: "venueId"))
        triggers.append(FSQPNearbyTrigger(triggerType: .category, fsqId: "categoryId"))
        triggers.append(FSQPNearbyTrigger(triggerType: .chain, fsqId: "chainId"))

        FSQPPilgrimManager.shared().nearbyTriggers = triggers
        List<NearbyTrigger> trigs = new ArrayList<>();
        trigs.add(new NearbyTrigger(TriggerPlaceType.CATEGORY, "categoryid"));
        trigs.add(new NearbyTrigger(TriggerPlaceType.CHAIN, "starbuckschainid"));
        trigs.add(new NearbyTrigger(TriggerPlaceType.PLACE, "specificvenueid"));

To handle nearby place notifications:

    // Inspect the nearbyVenues property on the visit object in - (void)fsqpPilgrimManager:(FSQPPilgrimManager *)locationManager didVisit:(FSQPVisit *)visit; as follows:
    func fsqpPilgrimManager(_ locationManager: FSQPPilgrimManager, didVisit visit: FSQPVisit) {
        // The `nearbyVenues` property is an array of regular `FSQPVenue`s
        if let nearbyVenues = visit.nearbyVenues {
            for nearbyVenue in nearbyVenues {
                // Handle nearby venue
    // Override the other method in PilgrimNotificationHandler as follows:
    protected static final PilgrimNotificationHandler pilgrimNotificationHandler = new PilgrimNotificationHandler() {
        public void handlePlaceNotification(Context context, PilgrimSdkPlaceNotification notif) {
        public void handleNearbyNotification(Context context, PilgrimSdkNearbyNotification notif) {
            List<NearbyVenue> nearby = notif.getNearbyVenues();
            // A `NearbyVenue` object has a normal `Venue` and a `List<TriggerPlaceType>` that tells you the kind of trigger that it matched. For example, if you were triggering on nearby coffee shops and Starbucks, a Starbucks would be returned with both Chain and Category place types.


In the standard integration of the Pilgrim SDK, the SDK will call your app with a notification that your user arrived at a place. From there it is likely that you will take some/all of the pieces of information that are handed to you, and send those up to your servers for logging or other actions like notification sending. This is a good flow for most apps, but does require the upfront work of defining the client/server protocol to get this information up from your application. To get around this, Foursquare offers the ability to have your servers called anytime one of your user arrives at a place.

Some possible benefits:

  • Reduced mobile network traffic and potential battery savings for your users via cutting out an API request to your servers from the device.
  • Faster development iteration on your side without having to deploy a new app version.
  • Allows Foursquare to potentially offer new data to you without requiring an app or SDK update.


You will configure the URL where you want the notifications to go to on the Pilgrim console page, which you can find more information about here.


The notification will come to your server endpoint as a x-www-urlencoded POST request. You can download example webhook notification JSON from Dropbox here.


Param Value
json The content of the notification in a JSON serialized string
secret String. A unique string that will be included on every request. You can find your secret in the developer console on the Pilgrim page.
arbitrary params In the SDK, there is a property available for you to set called userInfo. This is a set of arbitrary parameters that you set on the SDK that will then be passed through to your endpoint here. For example, if in the SDK you set a map containing “userId” -> “123456”, in the request to your server you would also see a parameter of “userId” alongside json. The arbitrary params should be set before starting the SDK.

The content represented in the JSON string from the top level parameter.

Key Type Description  
venues Array<Venue> The place the user is at. Currently a max of 1 item is sent.  
confidence String The venue confidence, which is one of none, low, med, high  
lat Double The latitude of the user when they arrived at the place  
lng Double The longitude of the user when they arrived at the place  
pilgrimVisitId String The unique ID of the visit. Required for confirming visits back to Foursquare  
timestamp long Time of the event in milliseconds since epoch  
visitType String The type of notification that is coming through: arrival, departure, historical.  
locationType String The type of place the event corresponds to. One of venue, home, work, none, unknown  
sdkType String The SDK that generated the notification iosSdk or androidSdk  
arrivalTime long Time of the arrival in milliseconds since epoch  
departureTime (Optional) long Time of the departure in milliseconds since epoch. Available on exit and historical visit types.  
otherPossibleVenues (Optional) Array<Venue> A list of other venues that the user might be at. Only returned if you have the checkbox selected in the Pilgrim console  
nearbyVenues (Optional) Array<Venue> The list of places nearby that matched your selected nearby triggers as configured on the Pilgrim console or locally in the SDK on a per user basis.  
Key Type Description
id String The venue id
name String The venue name
location Location The location of the venue
categories Array<Category> The categories of the venue
hierarchy (optional) Array<Venue> The parent venues of this place, containing a subset of venue information (id, name, categories)
venueChains (optional) Array<Chain> The chains that the venue belongs to
Key Type Description
crossStreet String Venue cross street.
address String The address of the venue
city String The city of the venue
state String The state of the venue
postalCode String The postal code of the venue
country String The country of the venue
lat Double The latitude of the venue center
lng Double The longitude of the venue center
Key Type Description
id String The category id
name String The category name
shortName String The shortened version of the category name i.e. American vs American Restaurant
pluralName String The plural name of the categories
icon Icon The category icon
Key Type Description
prefix String Url prefix
suffix String Url suffix
Key Type Description
id String The chain id

Example webhook payload

  "secret": "XXXXXX",
  "json": {
    "venues": [
        "id": "412d2800f964a520df0c1fe3",
        "name": "Central Park",
        "location": {
          "address": "59th St to 110th St",
          "crossStreet": "5th Ave to Central Park West",
          "city": "New York",
          "state": "NY",
          "postalCode": "10028",
          "country": "US",
          "lat": 40.788859944495,
          "lng": -73.961162567139
        "categories": [
            "id": "4bf58dd8d48988d163941735",
            "name": "Park",
            "pluralName": "Parks",
            "shortName": "Park",
            "icon": {
              "prefix": "https:\/\/ss3.4sqi.net\/img\/categories_v2\/parks_outdoors\/park_",
              "suffix": ".png"
        "venueChains": [

    "confidence": "med",
    "locationType": "venue",
    "pilgrimVisitId": "593eede7d48ec143c034a349",
    "visitType": "arrival",
    "timestamp": 1497296359056,
    "lat": 40.777502,
    "lng": -73.969508,
    "sdkType": "androidsdk"

Venue Harmonization

If you maintain your own venue database, you may want to know if a visit has occurred at one of those venues. We have a guide for venue harmonization in our API documentation, but we can also store a copy of the harmonization and return your venue Id in the Pilgrim visit callback. We enable this on a parter-by-partner basis, please contact us if you feel like this feature should be enabled for you. Once enabled, you will start seeing your venue Ids returned for visits where we have a mapping.

func fsqpPilgrimManager(_ locationManager: FSQPPilgrimManager, didVisit visit: FSQPVisit) {
    let partnerId = visit.venue?.partnerVenueId
    // Do something with your own venue Id
protected static final PilgrimNotificationHandler pilgrimNotificationHandler = new PilgrimNotificationHandler() {
    public void handlePlaceNotification(Context context, PilgrimSdkPlaceNotification notif) {
        String partnerId = notif.getContentId();
        // Do something with your own venue Id

Third Party Integrations

Many teams use a Mobile Marketing Automation (MMA) solution to manage events and create content based on those events. We now allow you to directly integrate the Pilgrim SDK events into the platform your company is using. If yours is not on the list, let us know and we can look into offering an integration with that as well. Similar to webhooks, we will send a notification to partners you have configured every time there is an arrival or departure event.


The only real requirement is to make sure that the user identifier that you use to denote a user to your MMA is also passed along through the Pilgrim SDK (examples below). Most require that that user already exists in their systems before accepting any events on their behalf. To sync those up, its just a simple method call to the SDK and that value will be transparently passed through to the MMA (not stored or used anywhere by Foursquare).

Here is a contrived example of how to get this up and running for an app that used both Localytics and Appboy.

// Where gaid is a previously set variable that stores the user's unique id:

// You can also set other custom fields using:
FSQPilgrimManager.shared().userInfo.setData('My custom value', forKey: 'myCustomField')
// Lets use the installid as the fake identifier that we register
String installId = PilgrimSdk.getPilgrimInstallId(this);

PilgrimUserInfo userInfo = new PilgrimUserInfo();

String sampleEmail = "pilgrim-mma-test@foursquare.com";

Localytics.autoIntegrate(this, "mylocalyticskey");

Next Steps

Check out the Changelog for the latest updates.