





















































(For more resources related to this topic, see here.)
First, you need to obtain an API key for the Google Geocoding API:
Now, we need to add a Salesforce remote site for the Google Maps API:
Next, we need to add a Location field to the Account object:
Next, we need an Apex utility class to geocode an address using the Google Geocoding API:
// static variable to determine if geocoding has already occurred private static Boolean geocodingCalled = false; // wrapper method to prevent calling future methods from an existing future context public static void DoAddressGeocode(id accountId) { if (geocodingCalled || System.isFuture()) { System.debug(LoggingLevel.WARN, '***Address Geocoding Future Method Already Called - Aborting...'); return; } // if not being called from future context, geocode the address geocodingCalled = true; geocodeAddress(accountId); }
// we need a future method to call Google Geocoding API from Salesforce @future (callout=true) static private void geocodeAddress(id accountId) { // Key for Google Maps Geocoding API String geocodingKey = '[Your API Key here]'; // get the passed in address Account geoAccount = [SELECT BillingStreet, BillingCity, BillingState, BillingCountry, BillingPostalCode FROM Account WHERE id = :accountId]; // check that we have enough information to geocode the address if ((geoAccount.BillingStreet == null) || (geoAccount.BillingCity == null)) { System.debug(LoggingLevel.WARN, 'Insufficient Data to Geocode Address'); return; } // create a string for the address to pass to Google Geocoding API String geoAddress = ''; if (geoAccount.BillingStreet != null) geoAddress += geoAccount.BillingStreet + ', '; if (geoAccount.BillingCity != null) geoAddress += geoAccount.BillingCity + ', '; if (geoAccount.BillingState != null) geoAddress += geoAccount.BillingState + ', '; if (geoAccount.BillingCountry != null) geoAddress += geoAccount.BillingCountry + ', '; if (geoAccount.BillingPostalCode != null) geoAddress += geoAccount.BillingPostalCode; // encode the string so we can pass it as part of URL geoAddress = EncodingUtil.urlEncode(geoAddress, 'UTF-8'); // build and make the callout to the Geocoding API Http http = new Http(); HttpRequest request = new HttpRequest(); request.setEndpoint('https://maps.googleapis.com/maps/api/geocode/json?address=' + geoAddress + '&key=' + geocodingKey + '&sensor=false'); request.setMethod('GET'); request.setTimeout(60000); try { // make the http callout HttpResponse response = http.send(request); // parse JSON to extract co-ordinates JSONParser responseParser = JSON.createParser(response.getBody()); // initialize co-ordinates double latitude = null; double longitude = null; while (responseParser.nextToken() != null) { if ((responseParser.getCurrentToken() == JSONToken.FIELD_NAME) && (responseParser.getText() == 'location')) { responseParser.nextToken(); while (responseParser.nextToken() != JSONToken.END_OBJECT) { String locationText = responseParser.getText(); responseParser.nextToken(); if (locationText == 'lat') latitude = responseParser.getDoubleValue(); else if (locationText == 'lng') longitude = responseParser.getDoubleValue(); } } } // update co-ordinates on address if we get them back if (latitude != null) { geoAccount.Location__Latitude__s = latitude; geoAccount.Location__Longitude__s = longitude; update geoAccount; } } catch (Exception e) { System.debug(LoggingLevel.ERROR, 'Error Geocoding Address - ' + e.getMessage()); } }
String geocodingKey = '[Your API Key here]';
Finally, we need to implement an Apex trigger class to geocode the Billing Address when an Account is added or updated
trigger geocodeAccountAddress on Account (after insert, after update) { // bulkify trigger in case of multiple accounts for (Account account : trigger.new) { // check if Billing Address has been updated Boolean addressChangedFlag = false; if (Trigger.isUpdate) { Account oldAccount = Trigger.oldMap.get(account.Id); if ((account.BillingStreet != oldAccount.BillingStreet) || (account.BillingCity != oldAccount.BillingStreet) || (account.BillingCountry != oldAccount.BillingCountry) || (account.BillingPostalCode != oldAccount.BillingPostalCode)) { addressChangedFlag = true; System.debug(LoggingLevel.DEBUG, '***Address changed for - ' + oldAccount.Name); } } // if address is null or has been changed, geocode it if ((account.Location__Latitude__s == null) || (addressChangedFlag == true)) { System.debug(LoggingLevel.DEBUG, '***Geocoding Account - ' + account.Name); AccountGeocodeAddress.DoAddressGeocode(account.id); } } }
The after insert / after update account trigger itself is relatively simple. If the Location field is blank, or the Billing Address has been updated, a call is made to the AccountGeocodeAddress.DoAddressGeocode method to geocode the address against the Google Maps Geocoding API.
Congratulations, you have now completed the Geolocation trigger for your Salesforce Account Object. With this, we can calculate distances between two objects in Salesforce or search for accounts/contacts within a certain radius.
Further resources on this subject: