+ Start a Discussion
salesforcedeveloper1.390550097000131E12salesforcedeveloper1.390550097000131E12 

Latitude Longitude using Geocoding api v3

Hi all,

I am using Google Geocoding api v3 to get latitude and longitude of the address present on my record and I am able to do so but
sometimes I get "OVER QUERY LIMIT" as error message even though I am not exceeding the api limits which is 2500 request per 24 hrs.
And I am requesting geocode for 1 address only i.e. not running a loop. I am not able to figure it out why this so

  User-added image

Below is the class using which I make callouts

public Class LocationCallOuts {
   
    /**
     *  DESCRIPTION   :    This method will create Address to be passed to get Latitude and Longitude of Address provided.
     *                     This method will also check that street name is not null, If street name is null then request is not made
     */
    public static void checkAddress(List<Risk_Location__c> riskLocationList) {
        List<Risk_Location__c> locationList = new List<Risk_Location__c>();
        List<Risk_Location__c> addressNotFound = new List<Risk_Location__c>();
        String streetValue;
        LocationCallOuts riskLocCall = new LocationCallOuts();
        for(Risk_Location__c riskLoc : riskLocationList) {
           
            streetValue = riskLocCall.GetStreetName(riskLoc);
            if(streetValue != null && streetValue != '') {
                locationList.add(riskLoc);
            } else {
                riskLoc.Address_Not_Found__c = true;
                addressNotFound.add(riskLoc);
            }
        }
        if( addressNotFound.size() > 0) {
           
            update addressNotFound;
        }
        if( locationList.size() >0 ) {
            riskLocCall.GetLocation(locationList);
        }
    }
   
    /**
     *  DESCRIPTION :       This method will be called to return Street Number.
     */
    @TestVisible private String GetStreetNumber (Risk_Location__c locStreetNumber) {
        String streetNumber = '';
        if(locStreetNumber.Street_Number__c != null && locStreetNumber.Street_Number__c != '') {
            streetNumber += locStreetNumber.Street_Number__c + ',';
        }
        return streetNumber;
    }
   
    /**
     *  DESCRIPTION :       This method will be called to return Street Name.
     */
    @TestVisible private String GetStreetName (Risk_Location__c locStreetName) {
        String streetName ='';
        if(locStreetName.Location__c != null && locStreetName.Location__c != '') {
            streetName += locStreetName.Location__c + ',';
        }
        return streetName;
    }
   
    /**
     *  DESCRIPTION :       This method will be called to return Suburb.
     */
    @TestVisible private String GetSuburb (Risk_Location__c locSuburb) {
        String suburbName = '';
        if(locSuburb.Suburb__c != null && locSuburb.Suburb__c != '') {
            suburbName += locSuburb.Suburb__c + ',';
        }
        return suburbName;
    }
   
    /**
     *  DESCRIPTION :       This method will be called to return State.
     */
    @TestVisible private String GetState (Risk_Location__c locState) {
        String stateName = '';
        if(locState.State__c != null && locState.State__c != '') {
            stateName += locState.State__c + ',';
        }
        return stateName;
    }
   
    /**
     *  DESCRIPTION :       This method will be called to return Country.
     */
    @TestVisible private String GetCountry (Risk_Location__c locCountry) {
        String countryName = '';
        if(locCountry.Country__c != null && locCountry.Country__c != '') {
            countryName += locCountry.Country__c + '}';
        }
        return countryName;
    }
   
    /**
     *  DESCRIPTION   :    This method is called to make request to Google with the address and get the Latitude and Longitude and update Risk Location records
     */
     @TestVisible private void GetLocation(List<Risk_Location__c> riskLocationList) {
         double lat = null;
         double lng = null;
         String address = '';
         String formattedAddress = '';
         List<String> splitAddress;
         Risk_Location__c riskLocation = new Risk_Location__c();
        
         for( Risk_Location__c riskLoc : riskLocationList ) {
             splitAddress = new List<String>();
            
             address += '{';
             address += GetStreetNumber(riskLoc);
             address += GetStreetName(riskLoc);
             address += GetSuburb(riskLoc);
             address += GetState(riskLoc);
             address += GetCountry(riskLoc);
            
             Http h = new Http();
             HttpRequest req = new HttpRequest();
             req.setEndpoint('http://maps.googleapis.com/maps/api/geocode/json?address='+address+'&sensor=true');
             req.setMethod('GET');
            
             try {
                 HttpResponse res = h.send(req);
                
                 JSONParser parser = JSON.createParser(res.getBody());
                 system.debug('********* Resquest Body ********' + res.getBody());
                 Boolean addressFlag = false;
                 Boolean latlngFlag = false;
                 while(parser.nextToken() != null ) {
                    
                     if((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'formatted_address') && addressFlag == false ) {
                        parser.nextToken();
                        formattedAddress = parser.getText();
                        addressFlag = true;
                     }
                     if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'location') && latlngFlag == false ) {
                           parser.nextToken();
                           while (parser.nextToken() != JSONToken.END_OBJECT) {
                               String txt = parser.getText();
                               parser.nextToken();
                               if (txt == 'lat')
                                   lat = parser.getDoubleValue();
                               else if (txt == 'lng')
                                   lng = parser.getDoubleValue();
                               if(lat != null && lng != null)
                                    latlngFlag = true;
                           } // End of Inner While Loop
                    }
                 }// End of while Loop
                
                 splitAddress = address.split(',');
                 // If Lat and Lng is not Null and Formatted address is same as Provided, populate Google Address, Address_Not_Found__c and Approximate_Address__c on Risk Location
                 if( lat != null && lng != null ) {
                     // If Formatted address from Google is same as Address on Risk Location, populate Lat, Lng, Google Address and Uncheck Approximate_Address__c and Address_Not_Found__c
                     if((formattedAddress.toUpperCase()).contains((splitAddress[1].toUpperCase())) && (formattedAddress.toUpperCase()).contains((splitAddress[2].toUpperCase())) &&
                        ((formattedAddress.toUpperCase()).contains(('AU')) || (formattedAddress.toUpperCase()).contains(('AUS')) || (formattedAddress.toUpperCase()).contains(('AUSTRALIA')))) {
                        riskLoc.Geolocation__Latitude__s = lat;
                        riskLoc.Geolocation__Longitude__s = lng;
                        riskLoc.Google_Address__c = formattedAddress;
                        riskLoc.Approximate_Address__c = false;
                        riskLoc.Address_Not_Found__c = false;
                     }
                     // If Formatted Address is not same as Address on Risk Location then Polpulate Lat,Lng,Google Address and Check Approximate_Address true and Address_Not_Found = false
                     else {
                        riskLoc.Geolocation__Latitude__s = lat;
                        riskLoc.Geolocation__Longitude__s = lng;
                        riskLoc.Approximate_Address__c = true;
                        riskLoc.Address_Not_Found__c = false;
                        riskLoc.Google_Address__c = formattedAddress;
                     }
                 }
                 // If Lat Lng is Null then Clear Google Address, Lat, Lng and Check Address_Not_Found = true and Approximate_Address = false
                 else {
                    riskLoc.Geolocation__Latitude__s = lat;
                    riskLoc.Geolocation__Longitude__s = lng;
                    riskLoc.Google_Address__c = '';
                    riskLoc.Approximate_Address__c = false;
                    riskLoc.Address_Not_Found__c = true;
                 }
             } catch( Exception e) {
                 system.debug('== Exception Occured ====' + e.getMessage());
             }
             address = '';
         } // End of For Loop
       
         update riskLocationList;
     } // End of Method
    
}

Please help me with this
Best Answer chosen by salesforcedeveloper1.390550097000131E12
puneet-mishrapuneet-mishra
mshelman is right,  the snapshot you have posted I can see that there is acustom button named "Get Geolocation "and you request for latitude and longitude on that button click, is it right. If it so I would suggest you to request for latitude and longitude using javascript instead of writting a whole class for it as it will be a server to server request.  writting a whole page to request geocode and update record in that page or write a javascript behind a button will make it client to server request which is easily tracable by google and you wont hit the limit.
Try below code, I have tried to used your fields ( change them acc. )
write behind your button or use same logic in your page.


{!REQUIRESCRIPT("https://maps-api-ssl.google.com/maps/api/js?v=3&sensor=false")}
{!REQUIRESCRIPT("https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js")}
{!REQUIRESCRIPT("../../soap/ajax/26.0/connection.js")}

var address = '{!Risk_Location__c.Street_Number__c}, ' + '{!Risk_Location__c.Location__c}, ' + '{!Risk_Location__c.Suburb__c}, ' + '{!Risk_Location__c.State__c}, ' + '{!Risk_Location__c.Country__c}';

sforce.connection.sessionId = '{!$Api.Session_ID}';

var geocoder = new google.maps.Geocoder();
var geocoderRequest = {
address: address
}

geocoder.geocode(geocoderRequest, function(results, status){
if(status == google.maps.GeocoderStatus.OK) {

var googleAddress = results[0].formatted_address;
var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
console.log('======googleAddress=====>' + googleAddress + '==== latitude ====>' + lat + '==== longitude ====>' + lng);

// updating a risklocation record
var riskTest = new sforce.SObject("Risk_Location__c");
riskTest.id = "{!Risk_Location__c.Id}";
riskTest.Geolocation__Latitude__s = lat;
riskTest.Geolocation__Longitude__s = lng;
sforce.connection.update([riskTest]);
window.parent.location = "/"+riskTest.id;//to reload the window and show the updated values

}
else if(status = google.maps.GeocoderStatus.ZERO_RESULTS) {
//YOUR LOGIN
}
else if(status = google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
// YOUR LOGIC
}
else if(status = google.maps.GeocoderStatus.INVALID_REQUEST) {
// YOUR LOGIC
}
});

All Answers

Bryn JonesBryn Jones
Query usualy means that it is looking for something....in your case it may be searching to much data from Google....or.....the address is not filled out completely.....

Hope this helps....please marka s asnwer it it did....

Bryn
mshelmanmshelman
You have to remember that you are on a salesforce instance and Google is counting ALL requests received from that IP not just yours....so it is difficult to get this to work well directly from Apex. One way to overcome this is to set up a server-side page on your own webserver to call Google geocode and call that page from Apex.
mshelmanmshelman
Sometimes it is helpful to search for an answer before posting

https://developer.salesforce.com/forums/ForumsMain?id=906F00000008xqnIAA

puneet-mishrapuneet-mishra
mshelman is right,  the snapshot you have posted I can see that there is acustom button named "Get Geolocation "and you request for latitude and longitude on that button click, is it right. If it so I would suggest you to request for latitude and longitude using javascript instead of writting a whole class for it as it will be a server to server request.  writting a whole page to request geocode and update record in that page or write a javascript behind a button will make it client to server request which is easily tracable by google and you wont hit the limit.
Try below code, I have tried to used your fields ( change them acc. )
write behind your button or use same logic in your page.


{!REQUIRESCRIPT("https://maps-api-ssl.google.com/maps/api/js?v=3&sensor=false")}
{!REQUIRESCRIPT("https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js")}
{!REQUIRESCRIPT("../../soap/ajax/26.0/connection.js")}

var address = '{!Risk_Location__c.Street_Number__c}, ' + '{!Risk_Location__c.Location__c}, ' + '{!Risk_Location__c.Suburb__c}, ' + '{!Risk_Location__c.State__c}, ' + '{!Risk_Location__c.Country__c}';

sforce.connection.sessionId = '{!$Api.Session_ID}';

var geocoder = new google.maps.Geocoder();
var geocoderRequest = {
address: address
}

geocoder.geocode(geocoderRequest, function(results, status){
if(status == google.maps.GeocoderStatus.OK) {

var googleAddress = results[0].formatted_address;
var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
console.log('======googleAddress=====>' + googleAddress + '==== latitude ====>' + lat + '==== longitude ====>' + lng);

// updating a risklocation record
var riskTest = new sforce.SObject("Risk_Location__c");
riskTest.id = "{!Risk_Location__c.Id}";
riskTest.Geolocation__Latitude__s = lat;
riskTest.Geolocation__Longitude__s = lng;
sforce.connection.update([riskTest]);
window.parent.location = "/"+riskTest.id;//to reload the window and show the updated values

}
else if(status = google.maps.GeocoderStatus.ZERO_RESULTS) {
//YOUR LOGIN
}
else if(status = google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
// YOUR LOGIC
}
else if(status = google.maps.GeocoderStatus.INVALID_REQUEST) {
// YOUR LOGIC
}
});
This was selected as the best answer
Sunil NandipatiSunil Nandipati
@puneet - i tried your suggestion on a similar requirement.  But it didnt work.  Do you mind taking a look at my code and suggest whats wrong with it.

Here is the post
https://developer.salesforce.com/forums/ForumsMain?id=906F0000000B1BQIA0