I have a site with a proximity search facility that is used by many visitors per day. With Google's new geocoding limit of 2500 per 24 hours per IP address, server-side geocoding is no longer possible (and caching won't work as we'll expect more than 2500 addresses to geocode per day, and rate-limiting isn't ideal either).

The "proper" way to do this is to to the geocoding client-side, and get the client to send the lat&lng to the server. Then you get 2,500 geocodes per visitor IP, rather than for the site.

https://developers.google.com/maps/articles/geocodestrat#client says:

When to use Client-Side geocoding

The basic answer is "almost always."

So we need a client-side geocoding widget, with an input box and JavaScript that will take a placename, geocode it client-side, and then send the lat&lng result back to the server to be processed.

I'm pretty busy with other things at the moment, but have a task on my To-Do list to implement this. Any help would be welcomed!

Comments

simon georges’s picture

Isn't it already what Geofield does with the "HTML5 Geolocation" widget?

kumkum29’s picture

Hello,

i have the same problem with a proximity search on my website (openlayers proximity module).
(post http://drupal.org/node/1954308)
Have-you found a solution ?

Thanks.

fonant’s picture

@Simon No, HTML 5 geolocation is for getting the location of the browser, i.e. the latitude and longitude of the person viewing the web page.

Geocoding is different, it's about taking any placename or address and getting the latitude and longitude of that.

simon georges’s picture

Yeah, after reading again, I totally understand the need. Sorry about the confusion.

user654’s picture

.

heng’s picture

Hi,

i had the same need and solved it by using the lat&lng exposed filter (from geofield) and adding a search field with google autocomplete functionality that updates the lat/lng fields in the callback function.
Not sure how to put this in the module though...

Brandonian’s picture

Priority: Normal » Major

This is a serious issue with Geocoder, and I think it's very important to add support for this, but it would likely be a pretty major architectural change to do so. I propose we look at this as something to do in either an 8.x branch or a 7.x-2.x branch of the module.

I've been thinking about the best way to handle this, and I think the only way that I can think of that isn't going to be insane for performance reasons is to allow for handlers to provide both an option for handling geocoding serverside and clientside. It's kind of terrible DX, but we can probably provide some tools for both plugin types to keep things simple for people wanting to plug into the system.

rdeboer’s picture

I guess the recently applied patch from #1672742: Avoiding OVER_QUERY_LIMIT due to more than 5 requests in a second in google geocode offers some relief, but I agree it would be better still to follow Google's advice as per the link at the top of this thread: https://developers.google.com/maps/articles/geocodestrat#client

From a UI perspective this could be done simply and elegantly. For instance with the Geofield (exposed) filter for Views, we'd have, next to the "Geocoding Service" drop-down, a tick box to "Use client-side version of this service".

The associated javascript file to be pushed to the client for each geocoding service could possibly be mentioned in geocoder_handler_info().

But the real challenge is how to deal with receiving the geocoded response from the client browser and whether to deal with it synchronously (blocking call, if that's possible at all) or asynchronously (non-blocking, AJAX).

I myself am not sure how to do it synchronously and am not sure whether it is even desirable: the server would wait (how long?) until the client has geocoded the address and sent it back to the server.

The asynchronous solution is technically easier. Server sends page + javascript to do the geocoding to execute geocoding client-side, but is not held up waiting for a response. Browser, when ready talking to the, say, Google service, posts the geocoded result to some Drupal menu callback to complete the process.
Problem: server has already moved on from the initial geocoder call, result comes in too late. This asynchronous use-case is great when all you want to do is put the result away in a database or session variable, but a pain for interactive scenarios.

One workaround in the latter scenario would be an automatic browser reload to activate the geocoded result in the page being viewed. This is easily done, but clunky.

Ideas anyone?

Rik

PS: having just looked at the Geocoder module code for the first time I noticed the function geocoder_service_callback(). In its comment it says that it's an AJAX service, but it isn't really in the sense that there's no Asynchronicity and no JAvascript involved. It's a synchronous server-side response to an HTTP GET request invoked by typing in your browser addresses like http://mysite.com/geocoder/service/google?data=Paris. As such it's a great test feature, but not one we can use as it stands to solve this issue.

Brandonian’s picture

Regarding synchronous callbacks, I set up a client project recently where we added a js form submit handler to a custom search form, which allowed us to hold off on actually submitting the form until we did an ajax request to a geocoder and submit the form once we received a result. Data was populated in a hidden form element. I imagine a similar solution would work well for us here. There's no reason why we couldn't architect it be asynchronous as well.

rdeboer’s picture

@Brandonian, #9

That sounds great and covers the use-case where the geocoding process is explicitly initiated from the client side.

But what about the case where a piece of PHP (e.g. a contextual or exposed filter in Views) calls the existing geocoder(..) function in geocoder.module with the expectation that the subsequent geocoding process is done client-side? That's the use-case I'm referring to in #8.

chandra_drupal’s picture

I have the same need for client side geo-coding, tried to get all the locations latitude and longitude from external sources and display them but baseless.

perignon’s picture

Just started working on a large project that involves a lot of mapping capabilities and I have eventually come upon this thread. I'll be needing to geocode far more than 2,500 addresses at one time (close to 200,000 at once), after that I will be done. But even attempting to "chunk" the amount up in 2,500 segments would have me working at it far too long. The client-side geocoding option I don't think would be possible.

What about the option of being able to use the Google Maps for Business API? Looking at the docs now it would be an easy change to the module. Problem is GMaps for Business doesn't have public pricing. Yahoo's Placefinder has a price listed on their website.

fonant’s picture

Issue summary: View changes

I'm not sure this problem is solvable in the Geocoder module, which really only provides server-side geocoding capabilities.

I've written a patch for Geofield so that its Views proximity search filter widget can do client-side geocoding: #2222929: Client-side Google Geocoding

JMBreitenbach’s picture

I'm sure that I'll get flack for reviving a "dead topic" but...

@Perignon google's Maps for Business starts at $10k/yr and goes up from there.

The easy way to do this is use the Google Javascript Maps API.

You do the geocoding client side and then only submit to server after it's complete.

Simple example

function getGeocodingInfo(){
var geocoder = new maps.google.maps.Geocoder();
//Get address from form - ADDRESS in example

geocoder.geocode({'address':ADDRESS}, function(results, status){
if(status == google.maps.GeocoderStatus.OK){
//prepare info to send to server
//Send to server
}
else{
//There was an error geocoding
}
});

}

fonant’s picture

@JMBreitenbach - that's exactly what my patch for Geofield does: #2222929: Client-side Google Geocoding

While the JavaScript is relatively easy, it's less easy to integrate it all with Drupal ;)

If you know what you're doing with the Google Maps API and client-side geocoding, please could you have a look at my patch, try it out, and suggest improvements?

Brandonian’s picture

So, I wrote a library awhile back that handles geocoding against multiple providers in JS. https://github.com/geocoder-php/geocoder-js

This is what the 8.x branch of the Geocoder module relies on for it's engine, and I think we should work on a) providing tools in Geocoder.module to help with this b) help improve the number of API's that Geocoder.js interacts with.

For a), I think that we can do this on a few different levels. Besides creating whatever js integration is needed to easily pull in the library, I think we could easily create a form api element that does basic auto-population based on geocoded results.

blacklabel_tom’s picture

Hi Brandonian,

Are there any plans to backport the library so the Drupal 7 version of this module uses it?

Cheers

Tom

wuinfo - bill wu’s picture

Moving to a client side, Google's new geocoding limit of 2500 per 24 hours per IP address is still not the best solution. What if people share same public IP address.

What if a map search returns 200 locations? After user going through a dozen pages, it stops working.

Since we store the latitude and longitude into our database, can we just use them to calculate the distance between 2 points?

pol’s picture

Status: Active » Closed (outdated)