Geolocation on Salesforce using Automatic Geocode and Google API’s

Sales and marketing professionals had challenges to assign territories and find their nearby prospects pertaining to a location. In order to get some useful data into the system, Salesforce partners and customers had to use number fields to store latitude and longitude pairs by having to manually type.

Salesforce unlocked a whole new way to understand their customers and run a business. Hence, they introduced Geolocation feature in Winter 2013, which enabled their customers to identify locations by their latitude and longitude. Subsequently, this feature was further enhanced to Geocode, which converts addresses into geographic coordinates like latitude and longitude and position the map.

Later, in Summer’16, Salesforce Automatic Geocode was introduced to automatically determine the distance between two geolocation fields and to run reports by distance. This feature provided value add to sales professionals by enabling to view their accounts, leads, contacts on maps and assign leads based on location. You can read more about Salesforce Automatic Geocode here.

Steps to set-up Geocode Clean Rules:

Prerequisite: The user must have ‘customize application’ permission to setup this rule.

  • Go to Setup-> Data.com Administration->Clean->Clean Rules.
  • In the clean rules page, there will be four Geocode rules which are inactive stage.
  • Select the rule and click on the edit link.
  • Review the Geocode clean rule settings and make any changes if required and click on save.
  • Activate the rule.

However, you can also get Geolocations for addresses in the records, such as Accounts, Leads and Contracts in Salesforce by making callouts to Google API.

Imagine a Trigger (before update) on a Lead object. This trigger will fire a batch class (so we don’t make the call directly from the trigger execution). The batch class will take the complete list of leads and will pass the list to a class that will make callouts to google API’s to get geo location for all leads in the list.

But first, please remember you will need to setup your Google API integration and get the authorization keys. Here you can find a good tutorial about how to get your keys and setup the Google API.

Also, you may consider creating an object to store the Google API custom settings. This way you can call the API Key, Base URL, Client Name and Request Path dynamically. On my example, my object is named Google API Setting (Google_API_Setting__c).

The class responsible for the call-out, will be something like this:

[sourcecode language=”csharp”] public with sharing class GeoCode {

static public Coordinates getAllLocation(Lead theLeadtheLead) {
String address = ”;
if (theLead.Street != null) {
address += theLead.Street + ‘, ‘;
}
if (theLead.City != null) {
address += theLead.City + ‘, ‘;
}
if (theLead.State != null) {
address += theLead.State + ‘ ‘;
}
if (theLead.PostalCode != null) {
address += theLead.PostalCode + ‘, ‘;
}
if (theLead.Country != null) {
address += theLead.Country;
}
address = EncodingUtil.urlEncode(address, ‘UTF-8’);
Google_API_Setting__c settings = GeoCoder.GetSettings();

Http h = new Http();
HttpRequest req = new HttpRequest();
String baseUri = settings.Base_URL__c;
String path = settings.Request_Path__c;

String apiKey = settings.API_Key__c;
apiKey = apiKey.replace(‘-‘, ‘+’).replace(‘_’, ‘/’);
Blob apiKeyBlob = EncodingUtil.base64Decode(apiKey);

String clientName = settings.Client_Name__c;
String baseRequest = path + ‘?&address=’ + address;
Blob urlBlob = Blob.valueOf(baseRequest);
String signature = settings.API_Key__c; //signature = signature.replace(‘+’, ‘-‘).replace(‘/’, ‘_’);

req.setEndpoint(baseUri + baseRequest + ‘&key=’ + signature);
req.setMethod(‘GET’);
req.setTimeout(60000);

HttpResponse res = h.send(req);
system.debug(‘res.getStatusCode()::’ + res.getStatusCode());
if (res.getStatusCode() == 200) {
JSONParser parser = JSON.createParser(res.getBody());
system.debug(‘response::’ + res.getBody());
double lat = null;
double lon = null;
while (parser.nextToken() != null) {
if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) & amp; amp; & amp; amp;
(parser.getText() == ‘location’)) {
parser.nextToken();
while (parser.nextToken() != JSONToken.END_OBJECT) {
String txt = parser.getText();
parser.nextToken();
if (txt == ‘lat’) {
lat = parser.getDoubleValue();
} else if (txt == ‘lng’) {
lon = parser.getDoubleValue();
}
}
}
}
return new Coordinates(lat, lon);
} else {
return null;
}
}

private static Google_API_Setting__c GetSettings() {
return Google_API_Setting__c.getOrgDefaults();
}

public class Coordinates {
public Double Lat {
get;
private set;
}
public Double Lon {
get;
private set;
}

public Coordinates(Double newLat, Double newLong) {
this.Lat = newLat;
this.Lon = newLong;
}
}
}
[/sourcecode]

If we are using the standard edition for API Callouts to Google, then we need to use the API KEY in the End Point URL. And the it will be like:

https://maps.googleapis.com/maps/api/geocode/json?address=Street+City+State
&key=YOUR_API_KEY

However, if we are using the premium version for API Callouts to Google, then we need to use Client Id as a parameter in the End Point URL. Something like:

https://maps.googleapis.com/maps/api/geocode/json?address=Street+City+State
&client=YOUR_CLIENT_ID&signature=SIGNATURE

This will get the Geolocation as a response from Google API. We can then use JSON to fetch the Geolocation with two parameters: Latitude and Longitude.

Not too complicated, right? I hope you find it useful.

See you next time!