Avoiding Google Maps geocode limit?

  • I'm creating a custom google map that has 125 markers plotted via a cms. When loading the map I get this message:

    Geocode was not successful for the following reason: OVER_QUERY_LIMIT

    I'm pretty sure it's the way in which I've geocoded the markers.

    How can I avoid these warnings and is there a more efficient way to geocode the results?

    UPDATE: This is my attempt at Casey's answer, I'm just getting a blank page at the moment.

    <script type="text/javascript"> 
    (function() { 
    
    window.onload = function() { 
     var mc;
    // Creating an object literal containing the properties we want to pass to the map 
    var options = { 
    zoom: 10, 
    center: new google.maps.LatLng(52.40, -3.61), 
    mapTypeId: google.maps.MapTypeId.ROADMAP 
    }; 
    
    // Creating the map 
    var map = new google.maps.Map(document.getElementById('map'), options); 
    
    // Creating a LatLngBounds object 
    var bounds = new google.maps.LatLngBounds(); 
    
    // Creating an array that will contain the addresses 
    var places = []; 
    
    // Creating a variable that will hold the InfoWindow object 
    var infowindow; 
    mc = new MarkerClusterer(map);
    <?php
    $pages = get_pages(array('child_of' => $post->ID, 'sort_column' => 'menu_order'));
    $popup_content = array();
    foreach($pages as $post)
        {
        setup_postdata($post);
        $fields = get_fields(); 
        $popup_content[] = '<p>'.$fields->company_name.'</p><img src="'.$fields->company_logo.'" /><br /><br /><a href="'.get_page_link($post->ID).'">View profile</a>';
        $comma = ", ";
        $full_address = "{$fields->address_line_1}{$comma}{$fields->address_line_2}{$comma}{$fields->address_line_3}{$comma}{$fields->post_code}";
        $address[] = $full_address;
        }
    wp_reset_query();
    echo 'var popup_content = ' . json_encode($popup_content) . ';';
    echo 'var address = ' . json_encode($address) . ';';
    ?>
    
    var geocoder = new google.maps.Geocoder(); 
    
    var markers = [];
    
    // Adding a LatLng object for each city  
    for (var i = 0; i < address.length; i++) { 
        (function(i) { 
            geocoder.geocode( {'address': address[i]}, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    places[i] = results[0].geometry.location;
    
                    // Adding the markers 
                    var marker = new google.maps.Marker({position: places[i], map: map});
                    markers.push(marker);
                    mc.addMarker(marker);
    
                    // Creating the event listener. It now has access to the values of i and marker as they were during its creation
                    google.maps.event.addListener(marker, 'click', function() {
                        // Check to see if we already have an InfoWindow
                        if (!infowindow) {
                            infowindow = new google.maps.InfoWindow();
                        }
    
                        // Setting the content of the InfoWindow
                        infowindow.setContent(popup_content[i]);
    
                        // Tying the InfoWindow to the marker 
                        infowindow.open(map, marker);
                    });
    
                    // Extending the bounds object with each LatLng 
                    bounds.extend(places[i]); 
    
                    // Adjusting the map to new bounding box 
                    map.fitBounds(bounds) 
                } else { 
                alert("Geocode was not successful for the following reason: " + status); 
                }
    
            });
    
        })(i);
    
    } 
    var markerCluster = new MarkerClusterer(map, markers); 
    } 
    })
    (); 
    </script> 
    

    It doesn't really matter what the solution is as long as the markers load instantly and it's not breaking any terms & conditions.

    You dont say why or how often you are doing these lookups. You arent trying to geocode the same points every page render are you? If thats the case you should be looking at using the api to do these lookups server side once only, when the location is first added to the database.

    If you want to try @Peter's advice, there's a simple tool here which will geocode the points in a Google spreadsheet. This would allow you write the lat/long for the cities into the CMS, so you wouldn't need to use the geocoder at run-time.

    @Peter Actually that sounds like a great idea. I'm a little torn as it will decrease the usability of my cms. If the client is having to find out lat/long per company rather than just entering the address then it's not very user friendly. Am I understanding that correctly?

    See my new answer lower down for a php function.

    could you give a link to the page you are working one. It doesn't seem to be http://www.mediwales.com/mapping/ because it is not a blank page.

    @simo I've reverted back to my original code from Casey's but think his answer is very close. If you view source on the link you'll see my code.

    @rob FWIW I think Ragi has the right approach. Casey's answer still requires that you geocode every point, every time the map draws, which doesn't appear to be necessary for your static dataset

  • Like everybody else, I could give you an answer with code, but I don't think somebody has explained to you that you are doing something that is fundamentally wrong.

    Why are you hitting this error? Because you are calling geocode every time somebody views your page and you are not caching your results anywhere in the db!

    The reason that limit exists is to prevent abuse from Google's resources (whether it is willingly or unwillingly) - which is exactly what you are doing :)

    Although google's geocode is fast, if everybody used it like this, it would take their servers down. The reason why Google Fusion Tables exist is to do a lot of the heavy server side lifting for you. The geocoding and tile caching is done on their servers. If you do not want to use that, then you should cache them on your server.

    If still, 2500 request a day is too little, then you have to look at Google Maps Premier (paid) license that gives you 100,000 geocoding requests per day for something around 10k a year (that is a lot - with server side caching you should not be reaching this limit unless you are some huge site or are doing heavy data processing). Without server side caching and using your current approach, you would only be able to do 800 pageviews a day!

    Once you realize that other providers charge per geocode, you'll understand that you should cache the results in the db. With this approach it would cost you about 10 US cents per page view!

    Your question is, can you work around the throttle limit that Google gives you? Sure. Just make a request from different ip addresses. Heck, you could proxy the calls through amazon elastic ips and would always have a new fresh 2500 allotted calls. But of course, besides being illegal (you are effectively circumventing the restriction given to you by the Google Maps terms of service), you would be doing a hack to cover the inherent design flaw you have in your system.

    So what is the right way for that use-case? Before you call the google geocode api, send it to your server and query if it is in your cache. If it is not, call the geocode, store it in your cache and return the result.

    There are other approaches, but this should get you started in the right direction.

    Update: From your comments below, it said you are using PHP, so here is a code sample on how to do it correctly (recommendation from the Google team itself) https://developers.google.com/maps/articles/phpsqlsearch_v3

    Have you got an example I could follow of sending it to the server etc?

    What is your backend CMS? (I assume you can/know how change it and just want a simple example that shows how to do that in your language of choice. You don't need an example of a client side js, or do you? Are you using any js framework like jquery?

    Also, you will need to give more context about how the marker data gets into your system in the first place

    @RagiYaserBurham I'm using wordpress with custom fields. The php bit is the part that grabs the data from the cms. A client side example of js would be handy.

    OK. Php then. This bit from the Google Documentation should include the mysql and php part http://code.google.com/apis/maps/articles/phpsqlgeocode.html

    For the javascript portion, I assume you know how to create a web service, so the call would use something like this http://api.jquery.com/jQuery.ajax/ of whatever you decide to do. Going into more details about how to write a web service or ajax call to a webservice is really outside of the scope of this forum

    I'm back onto this project. I've been looking for a while now of a way to save my wordpress data into a google fusion table but can't find the answers. I think this is the right direction to go.

    @RagiYserBurhum Hi. I've been looking into Google Fusion Tables and come across a few problems. 1. You have to manually geocode addresses (via file->geocode) in the table, can this be done automatically? 2. Some markers are only appearing at certain zoom levels while others show whatever the zoom level. This is the example - http://www.mediwales.com/mapping/example.

    See 10.1.3 (b) for details on what kinds of caching are allowed. https://developers.google.com/maps/terms#section_10_12

    How to do cache for javascript?

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM