Home and Work Detection

After ~72 hours the SDK will determine the user’s home and work location. You can see if this has been set by checking the hasHomeOrWork property.

iOS

FSQPPilgrimManager.shared().hasHomeOrWork()

Android

FrequentLocations.hasHomeOrWork(context)

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
            print(FSQPPilgrimManager.shared().homeLocations)
            print(FSQPPilgrimManager.shared().workLocations)
            
        } 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
        }
    }

Visit Feedback

Visit feedback is a way to give Foursquare feedback on a visit the SDK provided. Giving accurate feedback can help improve the speed an accuracy of future visits. To leave feedback, all you need is the visit id from the original visit.

iOS

- (void)provideFeedbackForPVisit:(NSString *)pVisitId feedback:(FSQPVisitFeedback)feedback actualVenueId:(nullable NSString *)actualVenueId completion:(nullable void (^)(NSError * _Nullable error, NSNumber * _Nullable httpStatusCode))completion;

The available feedback options are:

Feedback Description
confirm The visit was at the correct venue.
falseStop The user did not stop anywhere. If you are unsure, use deny
wrongVenue The wrong venue was detected. A Foursquare venue id can optionally be included to identify the correct venue.
deny Generic feedback that something was incorrect. If your feedback UX doesn’t allow for wrongVenue or falseStop or you are unsure, use this.

An example providing wrongVenue feedback with the correct venueId:

FSQPPilgrimManager.shared().visitFeedbackProvider?.provideFeedback(forPVisit: FSQPVisit().pilgrimVisitId!,
                                                                   feedback: .wrongVenue,
                                                                   actualVenueId: "4ed92126f5b92139871ce962",
                                                                   completion: nil)

Android

/**
 *
 * @param pilgrimVisitId - The visit ID from the notification that is sent to you.
 *                       Note not all enter notifications have visit ids.
 * @param feedback - The type of feedback you want to leave for the visit
 * @param actualVenueId - If you were at another venue than the one you were notified.
 *                      Pass the actual venue ID here.
 */
PilgrimSdk.leaveVisitFeedback(@NonNull String pilgrimVisitId, @NonNull VisitFeedback feedback, String actualVenueId)

The available feedback options are:

Feedback Description
VisitFeedback.CONFIRM The visit was at the correct venue.
VisitFeedback.WRONG_VENUE The wrong venue was detected. A Foursquare venue id can optionally be included to identify the correct venue.
VisitFeedback.DENY Generic feedback that something was incorrect. If your feedback UX doesn’t allow for wrongVenue, use this.

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:

iOS

func fsqpPilgrimManager(_ locationManager: FSQPPilgrimManager, didVisit visit: FSQPVisit) {
        let otherVenues = visit.otherPossibleVenues
        // Do something with the alternate venues
}

Android

 protected static final PilgrimNotificationHandler pilgrimNotificationHandler = new PilgrimNotificationHandler() {
        @Override
        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.

iOS

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

To handle nearby place notifications on iOS, you will 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) {

        if let nearbyVenues = visit.nearbyVenues {
            for nearbyVenue in nearbyVenues {       
                // Handle nearby venue
            }
        }
    }

The nearbyVenues property is an array of regular FSQPVenues

Android

To set nearby triggers on an individual device:

        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"));
        PilgrimSdk.get().setNearbyTriggers(trigs);

To handle nearby place notifications, you will override the other method in PilgrimNotificationHandler as follows:

 protected static final PilgrimNotificationHandler pilgrimNotificationHandler = new PilgrimNotificationHandler() {
        @Override
        public void handlePlaceNotification(Context context, PilgrimSdkPlaceNotification notif) {
        }

        @Override
        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.


Webhooks

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.

Setup

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.

Payload

The notification will come to your server endpoint as a x-www-urlencoded POST request.

Params

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.
JSON

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.  
Venue
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
Location
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
Category
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
Icon
Key Type Description
prefix String Url prefix
suffix String Url suffix
Chain
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.

iOS

  func fsqpPilgrimManager(_ locationManager: FSQPPilgrimManager, didVisit visit: FSQPVisit) {   
      let partnerId = visit.venue?.partnerVenueId   
      // Do something with your own venue Id   
  }

Android

 protected static final PilgrimNotificationHandler pilgrimNotificationHandler = new PilgrimNotificationHandler() {
        @Override
        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.

Requirements

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.

Android

// Lets use the installid as the fake identifier that we register
 String installId = PilgrimSdk.getPilgrimInstallId(this);

PilgrimUserInfo userInfo = new PilgrimUserInfo();
userInfo.setUserId(installId);
PilgrimSdk.get().setUserInfo(userInfo);

String sampleEmail = "pilgrim-mma-test@foursquare.com";
Appboy.getInstance(this).changeUser(installId);
Appboy.getInstance(this).getCurrentUser().setEmail(sampleEmail);

Localytics.autoIntegrate(this, "mylocalyticskey");
Localytics.setCustomerId(PilgrimSdk.getPilgrimInstallId(this));
Localytics.setCustomerEmail(sampleEmail);

Next Steps

Check out the Changelog for the latest updates.

Changelog