getButterfly Logo getButterfly

Map

Sometimes, just like myself with a recent project, you need to create a Google Map and populate it with markers extracted from an IP array. Hundreds, even thousands of IP addresses. In order to achieve this, you need to transform each IP to a location, then generate a marker and an info window.

Let’s get to work.

The code is split into 4 parts:

  1. The Google Maps script (note that you might need an API key)
  2. The IPMapper script (forked and modified for 2016)
  3. The array generation script
  4. The map element

Feel free to modify as required.

<script src="https://maps.google.com/maps/api/js"></script>
<script>
/*
 * IP Address Geocoding Using Google Maps
 * Forked from http://lab.abhinayrathore.com/ipmapper/ (June 13, 2012)
 *
 * Last Updated: May 17, 2016
 * @version 0.2.0
 */
var IPMapper = {
    map: null,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    latlngbound: null,
    infowindow: null,
    baseUrl: "https://freegeoip.io/json/",
    initializeMap: function(mapId) {
        IPMapper.latlngbound = new google.maps.LatLngBounds();
        var latlng = new google.maps.LatLng(0, 0);

        // Set map options
        var mapOptions = {
            zoom: 1,
            center: latlng,
            mapTypeId: IPMapper.mapTypeId
        }

        // Initialize map
        IPMapper.map = new google.maps.Map(document.getElementById(mapId), mapOptions);

        // Initialize info window
        IPMapper.infowindow = new google.maps.InfoWindow();

        // Info window close event
        google.maps.event.addListener(IPMapper.infowindow, 'closeclick', function() {
            IPMapper.map.fitBounds(IPMapper.latlngbound);
            IPMapper.map.panToBounds(IPMapper.latlngbound);
        });
    },
    addIPArray: function(ipArray) {
        // Get unique array elements
        ipArray = IPMapper.uniqueArray(ipArray);

        // Add a map marker for each IP address
        for (var i = 0; i < ipArray.length; i++) {
            IPMapper.addIPMarker(ipArray[i]);
        }
    },
    addIPMarker: function(ip) {
        // Validate IP address format
        // Note: You don't need this if you validate IP addresses server-side
        ipRegex = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/;
        if($.trim(ip) != '' && ipRegex.test(ip)) {
            var url = encodeURI(IPMapper.baseUrl + ip + "?callback=?"); // Geocoding URL
            $.getJSON(url, function(data) { // Get geocoded JSONP data
                if($.trim(data.latitude) != '' && data.latitude != '0' && !isNaN(data.latitude)) {
                    // Geocoding successful
                    var latitude = data.latitude;
                    var longitude = data.longitude;
                    var contentString = "";
                    $.each(data, function(key, val) {
                        contentString += '<b>' + key.toUpperCase().replace("_", " ") + ':</b> ' + val + '<br />';
                    });
                    var latlng = new google.maps.LatLng(latitude, longitude);
                    var marker = new google.maps.Marker({ // Create map marker
                        map: IPMapper.map,
                        draggable: false,
                        position: latlng
                    });
                    IPMapper.placeIPMarker(marker, latlng, contentString); // Place marker on map
                } else {
                    IPMapper.logError('IP Address geocoding failed!');
                    $.error('IP Address geocoding failed!');
                }
            });
        } else {
            IPMapper.logError('Invalid IP Address!');
            $.error('Invalid IP Address!');
        }
    },
    placeIPMarker: function(marker, latlng, contentString) { // Place marker on map
        marker.setPosition(latlng);
        google.maps.event.addListener(marker, 'click', function() {
            IPMapper.getIPInfoWindowEvent(marker, contentString);
        });
        IPMapper.latlngbound.extend(latlng);
        IPMapper.map.setCenter(IPMapper.latlngbound.getCenter());
        IPMapper.map.fitBounds(IPMapper.latlngbound);
    },
    getIPInfoWindowEvent: function(marker, contentString) { // Open marker info window
        IPMapper.infowindow.close();
        IPMapper.infowindow.setContent(contentString);
        IPMapper.infowindow.open(IPMapper.map, marker);
    },
    uniqueArray: function(inputArray) { // Return unique elements from array
        var a = [];
        for (var i=0; i<inputArray.length; i++) {
            for (var j=i+1; j<inputArray.length; j++) {
                if (inputArray[i] === inputArray[j]) {
                    j = ++i;
                }
            }
            a.push(inputArray[i]);
        }

        return a;
    },
    logError: function(error) {
        if (typeof console == 'object') {
            console.error(error);
        }
    }
}
</script>

<script>
$(function() {
    try {
        IPMapper.initializeMap("map");

        var ipArray = ["111.111.111.111", "222.222.222.222", "123.123.123.123"];
        IPMapper.addIPArray(ipArray);
    } catch(e) {
        //handle error
    }
});
</script>

<div id="map" style="height: 500px; margin: 24px 0; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.15);"></div>

That’s it! If you need more than 10,000 queries per hour, you can cache the addresses in a database table and only fetch new IP addresses.

Notes and credits:

  1. IPMapper
  2. With freegeoip.io, you’re allowed up to 10,000 queries per hour by default. Once this limit is reached, all of your requests will result in HTTP 403, forbidden, until your quota is cleared.
  3. Map image by John-Mark Kuznietsov

Subscribe to getButterfly Blog

Once a week or so we send an email with our best content. We never bug you, we just send you our latest piece of content.



If you found any value in this post, agree, disagree, or have anything to add - please do. I use comments as my #1 signal for what to write about. Read our comment policy before commenting! Comments such as "Thank you!", "Awesome!", "You're the man!" are either marked as spam or stripped from URL.

Leave a Reply

Your email address will not be published. Required fields are marked *