Show your blog’s visitors on map with Shiny

Datetime:2016-08-22 23:47:23          Topic: JavaScript  JSONP           Share

You may have interest about who visited your web site, and it’s better if you can see them on map, like this one . In this blog, I will show you how to create a such kind of shiny-app to track your visitors.

A shiny-app is a web site which allow users to interactively input and get output. The idea of creating a visitor-tracking shiny-app is: when users open your blog site, a shiny-app will also be opened ( which can be embedded in your web site ), and once the shiny-app be opened, it will save user’s IP related information to your server.

JavaScript code for getting the IP related information:

$(document).ready(function(){
  var I = 0
  var tt = setInterval(function(){
    var L = $("#log");
    $.get("http://ipinfo.io", function(e) {
      L.val(Date() + "  ipInfo|" + e.ip + "," + e.city + "," + e.loc);
      L.trigger("change");
    }, "jsonp");
    if(L.val().length > 0) {
      clearInterval(tt)
    }
  }, 100)
});

Where #log is a textInput input of shiny for storing the IP related information.

The following part in above is used to get the IP related information and store it into “#log”, and tell shiny-app that the value of “#log” has changed. So, we can write some code in “server.R” to save the value of “#log” into server.

    $.get("http://ipinfo.io", function(e) {
      L.val(Date() + "  ipInfo|" + e.ip + "," + e.city + "," + e.loc);
      L.trigger("change");
    }, "jsonp");

And the following part is used to stop continue fetching IP information:

    if(L.val().length > 0) {
      clearInterval(tt)
    }

In server.R

The code for storing IP information:

  observe({
    msg <- gsub(".*ipInfo", paste(date(), "ipInfo"), input$log)
    if (nchar(msg) > 20) {
      write(msg, "www/visitors.txt", append  = TRUE)
    }  
  })

The code for map:

  output$myMap <- renderMap({
	Dat <- rDat()
	Map <- Leaflet$new()
	Map$addParams(width="100%", height="800px;", layerOpts = list(maxZoom = 18, zoomControl = FALSE))
	Map$addParams(bounds = list(c(min(Dat$Lat), min(Dat$Lon)) - 10, c(max(Dat$Lat), max(Dat$Lon)) + 10))
	Points <- as.list(rep(NA, nrow(Dat)))
	for (i in 1:nrow(Dat)) {
	  Points[[i]] <- c(lat = Dat$Lat[i], lon = Dat$Lon[i], 
					   value = paste(Dat$City[i], as.character(Dat$Time[i]), sep = ": "))
	}
	Map$addParams(cluster = Points)
	Map
  })

where Map$addParams(cluster = Points) creates an object called “spec.cluster”. We need to add the following JavaScript code at the end of /usr/local/lib/R/site-library/rCharts/libraries/leaflet/layouts/chart.html to show the cluster points.

 if (spec.cluster != undefined) {
	var markers = L.markerClusterGroup();
		for (var i = 0; i < spec.cluster.length; i++) {
			var a = spec.cluster[i];
			var title = a.value;
			var marker = L.marker(new L.LatLng(a.lat, a.lon), { title: title });
			marker.bindPopup(title);
			markers.addLayer(marker);
		}
		map.addLayer(markers);
	}

We also need include some JavaScript libraries needed into /usr/local/lib/R/site-library/rCharts/libraries/leaflet/external , they are:

  • MarkerCluster.css

  • MarkerCluster.Default.css

  • leaflet.markercluster-src.js

To include above libraries, we need to modify the file /usr/local/lib/R/site-library/rCharts/libraries/leaflet/config.yml as:

leaflet:
  css: 
    - external/leaflet.css
    - external/MarkerCluster.css 
    - external/MarkerCluster.Default.css

  jshead:
    - external/leaflet.js
    - external/leaflet.markercluster-src.js

All scripts (includes demo data) can be downloadedhere. Remember backup the leaflet folder before replacing it with the one in download folder ( www/leaflet ).





About List