Discuss & Vote

Live Traffic travel time Tile! Image from query text using Shields.io

Rob Cummings 7 years ago in Media Tiles / Weather & Traffic updated by Ted Chen 4 years ago 95

I thought I'd post this to help others. I figured out a way to display the travel time for my wife's commute to work. See the pink tile in the screenshot below...

Image 1599

I used a Google Maps Distance Matrix API call and displayed the result in a Shields.IO badge. (Check out http://shields.io) Then I added the whole darn deal to the My Media section in Action Tiles.

Here's the link I used, broken into pieces...

Base URL: https://img.shields.io/badge/dynamic/json.svg

Badge Options (no label, pink color, time query, badge style): ?label= &colorA=ff69b4&colorB=ff69b4&prefix=&suffix=&query=$..duration_in_traffic.text&style=flat-square

Google Maps API call: &uri=https%3A%2F%2Fmaps.googleapis.com%2Fmaps%2Fapi%2Fdistancematrix%2Fjson%3Funits%3Dimperial%26departure_time%3Dnow%26origins%3D[origin address]%26destinations%3D[your destination address]%26key%3D[your API key]

You'll have to generate and use a Google API key and the URI has to be encoded with all those silly % escape codes. The Dynamic Generator at the bottom of the Shields.io page will help you out with the pieces. It was a bit of trial and error. Here's what it looks like all put together in the My Media image URL field...

https://img.shields.io/badge/dynamic/json.svg?label= &colorA=ff69b4&colorB=ff69b4&prefix=&suffix=&query=$..duration_in_traffic.text&style=flat-square&uri=https%3A%2F%2Fmaps.googleapis.com%2Fmaps%2Fapi%2Fdistancematrix%2Fjson%3Funits%3Dimperial%26departure_time%3Dnow%26origins%3D[your origin address]%26destinations%3D[your destination address]%26key%3D[your API key]

As everything seems to be, it's a little bit of a hack (text not centered), and the image and text proportion is stretched/crunched from the original (just like weather maps, camera images, etc.) but it seems to be working pretty well. One of the cool things is that it's actually an SVG, so no quality is lost if you make the tile bigger or look at it in a full-screen view. 

Hope this helps!

Discuss & Vote

I have to read and digest this carefully, but potentially this could be HUGE!


Shields.io is open source and really just takes JSON (in this case) or XML output and puts it in a PNG or SVG. I don't know why it didn't occur to me before, but you guys could adapt this code and method to display almost any dynamic API information. (Though in my non developer brain I'd think it would be easier to just display the JSON query text as native text.)


Thanks for sharing this innovative work, Rob!

Yes: We have had requests for "generic text output" Tiles; and sophisticated variants like "gauge Tiles".

The main hang-ups?

  • We'd like to get all our data from SmartThings. In many ways it keeps it simple. We can trust SmartThings to handle all the security and API intricacies of subscribing to the sources of the data and returning results in an expected way.
  • We need to know and expect something about the resulting text so that it can be formatted appropriately and consistently in the Tile. Since Tiles can be many shapes and sizes, and content and fonts can also be sized, it is quite difficult to predict what will fit in the Tile and what to do when a result text doesn't fit.

The above bullets are just speed bumps, not road-blocks. We just have to reiterate that there is "no such thing as a simple Feature". Everything takes time to figure out, design, implement, test, Beta test, and so on.

So we're grateful when y'all come up with pragmatic solutions like this which can tide us over!

Implementing a custom tiles from shields.io would actually save you a lot of hassle.

Shields.io does not only return images but also a standard json 



  • name: "custom badge",
  • value: "no query specified"


You can now expect something about the resulting text so that it can be formatted appropriately and consistently in the Tile.

That would allow SO MUCH MORE possibilities (AT is already awesome) and leave the hassle of formatting and playing around with shields.io to the end-user. We can now go strip any other json request and pass it in a standard way to AT.

Great point, Oliv...

We have a few Feature Requests (variations) to add functionality for REST-API calls or other ways to push data to a Tile or pull data or images or website frames into a Tile, etc..

Your shields.io JSON query example is help.

But please visit at least this one existing Topic to add Votes and perhaps a relevant use-case comment:  https://support.actiontiles.com/communities/12/topics/3615-api-calls-to-external-services


Excellent!  I had to play with it for a while to figure out the full text of the query (apparently I added an extra underscore in the destination) but it provides exactly what I needed.

Rob Cummings....Pardon my ignorance.....But I would love to give this a whirl, but I have no earthly idea where to begin other than the shields.io link. Would it be possible to post a tutorial?

And/or some more examples if others are using this.  I spent a few minutes trying to make a scoreboard from NBA JSON data but didn't get it working.


I'm not a programmer and probably spend way too much of my life doing this stuff by trial and error.

For the the traffic time, the biggest part is to generate a Google API key that allows you to make the API calls. https://console.developers.google.com/apis/credentials  You'll need to log in and generate a new key. When you generate a new key, you'll see a long string of random numbers and letters. That's your key. Don't ever post it anywhere publicly.

For the Shields.io part, you can use their website or hack together your own URL until it looks something like this:

origin address]%26destinations%3D[your destination
address]%26key%3D[your API key]

Here's the basic Google API URL:


I figured out the API call in my browser first. When I was sure I was getting the information I wanted. I added that link to the Shields.io generator. Then I figured out how to query just the information I wanted.

That's the $..duration_in_traffic.text part. When Shields gave me the whole combined URL, I copied and pasted that link into the My Media URL in Action Tiles. 

In Shields...

Type:  json

label:  (space)

uri:  The Google API URL

$.data.subdata (This is the query that extracts just the duration in minutes):   $..duration_in_traffic.text

hex color: (whatever you want)

Nothing for prefix or suffix

Hopefully this helps!

I'm having a hard time getting this to work, can anyone help me out please?

I have created an API Key and I am able to get mileage and drive time to show on a webpage.

   "destination_addresses" : [ "555 Somewhere, Columbus, OH 43215, USA" ],
   "origin_addresses" : [ "555 No Where, Columbus, OH 43220, USA" ],
   "rows" : [
         "elements" : [
               "distance" : {
                  "text" : "11.3 mi",
                  "value" : 18250
               "duration" : {
                  "text" : "15 mins",
                  "value" : 911
               "status" : "OK"
   "status" : "OK"

  I then open Shield.IO webpage and select 


space for label,

 url from maps.googleapis.com 

change next tab to $..duration_in_traffic.text (i have even tried $.data.subdata)


insert a space for prefix and suffix.  (I even deleted space and allowed prefix and suffix)

I am doing this under Dyamic portion on Shield.IO (almost bottom of the webpage).  When I click generate, I get a black box to the left and a green box to the right. 

 I then try Rob's final URL and placed my information into that.  After hacking it up, I get a pink custom badge and no information. It almost seems like the webpage isn't being pulled up.

My Final URL after replacing info




So who do I have to PayPal money to for beer to do this for me if I give you all the information you need to make this happen?

Thank you so much.  I got the time to work!!!!

One last question if I can bother you.  My tile says Custom Badge, do you know how I can get rid of that?

Very much interested in generating a driving distance tile.

I have been trying, but with no luck. I know I'm missing something but can't piece it together as of yet.

Here is what I have done.

1) Went to the Google Maps APIs (https://developers.google.com/maps/documentation/distance-matrix/) and selected the Duration and Distance link which took me to a getting started page. 

2) Selected "Activate the API and get an API key" link on the right of the page.

3) Selected "GET A KEY" which gave me an API key.

4) Took their example request [https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=Washington,DC&destinations=New+York+City,NY&key=Your API KEY

    and substituted the origins and destinations with my origin and destination using + symbol for the spaces.

5) I then put that URL in my browser and it generated a web page like Ryan's showing disance.text to be 16 miles and a duration of 28 minutes...so I assumed that it was working.

6) I then took that URL and 

       a) Put &uri= in front

       b) Substituted %3A%2F%2F for :// and %2F for all the / , %3D for all the = signs and %3C for the commas.

7)  On the shield.io website near the bottom I put:

     Type:  json

     label:  nothing

     uri:  The Google API URL with the replacements I made in step 5 above

    $..duration_in_traffic.text  in the $.data.subdata

    hex color: dragged the color:blue icon to this field.

    Left prefix and suffix  blank

8) Then I selected Generate

8) Unike Ryan all I get is a badge with a grey "custom badge" on the left and a green "inaccessible" on the right.

Can anyone see where I might be going wrong here?

Much appreciated!



When I done it the way you did, it was missing departure_time=now , do you have that in the html code? I would take Rob's code and put your addresses  in it.  

Also, you don't need to do the replacements before Shields.io, it will replace all the characters for you.

I was able to remove the Custom Badge.  If anyone is curious, 


Nice solution. I'm tempted to code a mini map solution with the travel time in the corner. Maybe use chrome headless or something.


Thank you Ryan...I got it working using Rob's code. I think I changed something in the conversion of the address getting rid of the spaces and commas with % signs.

Hi to all,

For some reason, I get a JSON answer :

         "elements" : [
               "distance" : {
                  "text" : "29.5 km",
                  "value" : 29533
               "duration" : {
                  "text" : "35 mins",
                  "value" : 2106
               "duration_in_traffic" : {
                  "text" : "33 mins",
                  "value" : 1950
               "status" : "OK"
   "status" : "OK"

But I can only get "duration" to work "duration_in_traffic" is blank ... any ideas ?

Make sure you don't have an extra underscore in departure_time.  I had the same problem and removing that second underscore solved it


I saw this and on a lark was able to make it work. I have one for each of the drive times to my two favorite boat ramps. I opened Rob's link in a separate window, edited for colors and address, then added my own API key and it worked. Awesome job. Thanks for the heavy lifting Rob. 


Hi all, been reading up on this and I'm able to generate a link for specific addresses and I know how to get a link to show traffic distance and time, but I have absolutely no idea how to get this to show up in AT or why I'd need an API:


Can someone please help me out with a walkthrough? I'd appreciate it

I managed to get this to work once, then it failed every time... I think they have changed the quota system for the API and it wont work without setting up a billing account... Can anyone confirm this to be correct please?

Yes, I think you're right. There is still a free tier, though, so as long as you're not generating a ton of traffic, you should be OK.

Yes, Google now requires a billing account to use these APIs.  They then give you the first $200/month of use for free--if I remember the math right, that is about 20,000 API calls per month.  My concern was the that my number of API calls was going to exceed the free time.  I was doing 5 minute traffic updates for three locations on two devices (51,840 calls in a 30 day month).  I just moved the traffic times to a different panel that I call from my main panel so that the traffic times API only gets called a few times a day.


This is an interesting observation, and idea. Does anyone know of a way to generate dynamic traffic map images, like weather radar images, but for traffic. You could create a panel with a traffic map and multiple common destination travel times. Hmmmm

I use Kevin1's ideal below to show a Bing traffic map.  I can't get a Google traffic map to show up as a media tile, but the Bing one will.  You will need a Bing API and to be careful on your refresh rate--they don't require a billing account but will cut you off when you exceed your limit.

The Bing solution above will let you get the zoom settings you want.  This Google solution will work for general traffic (from another traffic post):

1. Google "San Francisco Traffic" (or your city)

2. Right click on the image in the Google search and "copy image location"

3. Make media location, "this media is image or gif" and set the update rate to 60 (or whatever)

Looks like its $300 for the first year - and then the following year you pay standard rates. Its not expensive but it's still money.


I saw this thread and thought it was a great idea but like Adam, mine worked once and then I looked at my daily quota and my 1 of 1 requests was used.  So I added this to my ActionPiXX program and now I get drive time tiles once again.  
I really like Todd's idea of the maps, but the way Google does things is insane, so the map feature may take some work.
I hope to have a beta release of ActionPiXX posted in the near future to get some feedback.  http://jayhobo.com/actionpixx
The Drive Time Tiles only update every 15 minutes.
Google being Google the "Drive Time Tiles" are "experimental" since Google changes things almost daily and they could break again at anytime.



if you go to google.com and search for "chicago traffic" it will show an image that you can right click, open in a new tab.  You can use this URL as an ActionTiles media tile.  There doesn't seem to be a way to adjust the position and zoom of the map.  It just shows the whole city or state that you searched for.  

There is also a Bing map that needs an API KEYbut I haven't been using it, don't know if the data is good any more...




You can use Waze also.

1) go to https://www.waze.com/livemap

2) Enter where you are going

3) Enter your origin address

4) This will display a map with all the driving times for all the different road possibilities.

5) Click the "Share Routes" button and copy that URL



The link will display traffic accidents, road construction, etc.

I'm not sure if you can get it to *not* show waze users on the map.


I love this Waze livemap...but how do I incorporate it into ActionTiles?

Straight URL does not work for me. Experimented by putting into urlencoder.org without success.

Hello Jay, It appears as the base URL that Waze uses has now changed since your instruction. Additionally, I don't think anyone here is clear on *how* you're using this. As just using this with shields.io provides no 'query', and it's no 'text' only to convert to an image. I'm not seeing an option to add this in the media tiles at all. What option are you using exactly to make this work?

I've given up on Waze.  I've been using my application for drive times and even then I don't use it that often as Google throws errors now and then also and I haven't had much time to look into why that is...


I like this solution. I wish we had a little more control over the formatting and size, but its still pretty cool. Here are 2 badges I made for the next rocket launch since I am in that business and this is useful to me. 



thanks for the tip!

If you struggle encoding your url properly : https://www.urlencoder.org/

This service makes it easy to integrate almost anything with an API... 

Mine broke, and I am not sure how to fix it.    invalid query parameter: url

looks like they changed the api output format. i changed to xml format and it seems to work again






Yeah, mine broke too. I removed "&prefix=&suffix=" and it works again. 

Here's the format I'm using...

%26origins%3D[ORIGIN ADDRESS]
%26destinations%3D[DESTINATION ADDRESS]
%26key%3D[API KEY]

https://img.shields.io/badge/dynamic/json.svg?label=&colorA=purple&colorB=purple&query=$..duration_in_traffic.text&style=flat-square&uri=https%3A%2F%2Fmaps.googleapis.com%2Fmaps%2Fapi%2Fdistancematrix%2Fjson%3Funits%3Dimperial%26departure_time%3Dnow%26origins%3D[ORIGIN ADDRESS]%26destinations%3D[DESTINATION ADDRESS]%26key%3D[API KEY]

Thank you so much, yours worked for me!

Mine still doesn't work, following these directions.

Very strange, but my google link works.

Here is an example, with fake information


and the google link which works


What am I missing?

I'm on mobile, so I can't really analize your link, but I suggest double checking that your spaces and underscores are correct.  I had an extra underscore in departure time that caused me no end of headaches.


This solution works very well. It does require a credit card to be connected to a  Google API developer account. If you don't have a credit card the API key can only be used once a day. This is really crappy for testing purposes.

This solution doesn't appear to be free anymore. Google's previous pricing allowed for up to 2,500 requests per day for the Directions API and Distance Matrix API (https://developers.google.com/maps/previous-pricing). This would have covered even heavy ActionTiles usage.

The new pricing model leaves a bit to be desired (https://cloud.google.com/maps-platform/pricing/sheet/). It costs $0.005 per Google API call for the Directions and Distance API's for 0-100,000 calls. The rate goes down to $0.004 for 100,001-500,000 calls (I doubt anyone would hit this range for dashboard use). 

I'll be moving this media tile off my main dashboard so it isn't displayed all the time on my Kindle Fire's home screen. The reason why is that the device is setup to refresh the screen every 5 minutes due to freezing problems with Foscam cameras (the MJPEG stream appears to freeze in regular browsers so its a quick and dirty work around). 

If I call the google API every 5 minutes it looks like i'll rack up a bill of $1.44 a day. Compare this to hiding the API calls in another dashboard that I only need to use once a day and I only rack up a bill of $0.16 a month. Since you get a $300.00 credit for setting up a billing account i'll let it run every 5 minutes for a day or two to make sure this cost structure is correct. Google is going pay to play I guess.


I ended up going with the Bing API

(https://docs.microsoft.com/en-us/bingmaps/rest-services/routes/calculate-a-route) which is totally free. However, it only provides that value in seconds. So I had to stick Runkit in between Bing and shields.io to do the conversion to minutes. It's kludgy as hell but the result: 

Can you write your url and query you used ?

I'm getting no results from shields.io but have the xml returned from bing site.

Anyone was able to use waze api ?
It will be great to see the waze live map and the route of home to work 

and/or to use waze estimate time to work like other did with google 

This works perfectly! Thanks a lot. I use the default tiles whenever possible, even if it means creating custom tiles in the IDE and all that Jazz. But there were some data I couldn’t get because of measurement units and data type. So thanks a lot for all your help!

Quick question I’m hoping has an easy solution: my icon has a grey background behind it. Rather than stretching to fill the tile size (no matter what I set it to). Is this some setting I have wrong in AT? 

So it definitely looks a like it’s just throwing the icon on top of a generic blank tile, rather than stretching it to fill the tile like a lot of the examples I see here. I just started with AT so I may be missing something obvious


Ok yep it was a pretty obviously solution. I wasn’t looking at the part in the URL where value= . So took that out and there it is! Looks good on my panel honestly it looks like it belongs lol

I’ve never used the google maps API but after taking a quick look at the request parameters on their documentation it looks like you can put any location format and google will convert it to Lat/Lon. I think the easiest and mostly accurate way for you to use specific address would be to change the zip codes to Latitude and Longitude.

Also I would edit and redact your API key in your OP if I were you 😇

Is this software still active? Anyone out there that can help with my inquiry? 

What are your 2 addresses?

6739 Marty St, Overland Park, KS 66204


2401 Gillham Rd Kansas City MO 64108

Any direction you can give on how to do it would be treat too! Thanks! 


change "YOUAPIKEYHERE" to your Google map API key :


You have to encode you url from :




Many tools exist on the web

Would anyone care to please paste their Bing Maps URL (with API Key redacted of course) - I'm struggling to get the correct Query parameter for TravelDuration (using either JSON or XML)

Much obliged!

Mine is:
 "https://dev.virtualearth.net/REST/v1/Routes/Driving?waypoint.1=45.111111,-75.11111&waypoint.2=45.1111,-75.11111&travelMode=driving&distanceUnit=mi&durationUnit=minute&key="+ query.apikey;

Cheers for the reply Israel. 

Alas I have that part working, its the next step, converting it to a badge/media tile showing the travel time I can't seem to get right.

Regardless of if I use XML or JSON, selecting just that variable with the syntax is doing my head in :)

Bing Maps API I'm testing:


XML Attempt

%3Forigins%3D [ORIGIN ADDRESS]
%26destinations%3D [DEST. ADDRESS]
%26key[API Key]

https://img.shields.io/badge/dynamic/xml.svg?label=Drive%20Time&query=//Response/ResourceSets/ResourceSet/Resources/Resource/Results/Distance/TravelDuration&uri=https%3A%2F%2Fdev.virtualearth.net%2FREST%2Fv1%2FRoutes%2FDistanceMatrix%3Forigins%3D [ORIGIN ADDREDSS]%26destinations%3D [DEST. ADDREDSS]%26travelMode%3Ddriving%26o%3Dxml%26key[API Key]

JSON Attempt

%3Forigins%3D [ORIGIN ADDRESS]
%26destinations%3D [DEST. ADDRESS]
%26key[API Key]

https://img.shields.io/badge/dynamic/json.svg?label=Drive%20Time&query=$.resourceSets.resources.results.travelDuration&uri=https%3A%2F%2Fdev.virtualearth.net%2FREST%2Fv1%2FRoutes%2FDistanceMatrix%3Forigins%3D [ORIGIN ADDREDSS]%26destinations%3D [DEST. ADDREDSS]%26travelMode%3Ddriving%26o%3Djson%26key[API Key]

I'm definitely missing something, likely the selection of the variable containing the duration in the query?

I get a valid time under the travelDuration variable when I put in legitimate Lat/Long co-ordinates.

I just can't seem to select this variable and return the value.

Any thoughts?

Hi ,
I'm getting results from this link but when I try to add img.sheilds it give me invalid error
https://img.shields.io/badge/dynamic/xml.svg?url=https://dev.virtualearth.net/REST/v1/Routes/Driving?waypoint.1=32.28767,34.944118&waypoint.2=32.262513,34.859375&travelMode=driving&distanceUnit=mi&durationUnit=minute&key=<api key>

I think I should add

query to the end of it as I get lot's of data returned and needs to pull out only the travelDuration but couldn't figure out how .


Hi Zvika,

Try JSON output, I managed to get the query dialed in for travelDuration so am happy to share.

You need to change the output of the Bing Maps response, add  "&o=json" to the Bing Maps Query

https://dev.virtualearth.net/REST/v1/Routes/Driving?waypoint.1=32.28767,34.944118&waypoint.2=32.262513,34.859375&travelMode=driving&distanceUnit=mi&durationUnit=minute&o=json&key=<API KEY>

Use the json response query for shields.io


Use this as your query parameter


Note: I used http://jsonpath.com/ to help step through each set of parameters until it selected the variable I wanted.

E.g. I pasted in the response I got from the Bing Maps and changed the JSONPath Syntax query to slowly work through the bracketed variables.

The kicker that got me was the [:1] as I wan't trating the brackets as Arrays. Its essentially saying the 1st entry in this array, in case there are more than 1.

Now visit use the dynamic creator on the https://sheilds.io main page to piece the above 3 parts all together as it also base64 encoded the bing maps URL.

So your full test URL should be (although I think it's outputting in seconds... you'll have to look into that)

https://img.shields.io/badge/dynamic/json.svg?label=Drive%20Time%20%28mins%29&query=%24.resourceSets%5B%3A1%5D.resources%5B%3A1%5D.routeLegs%5B%3A1%5D.travelDuration&url=https%3A%2F%2Fdev.virtualearth.net%2FREST%2Fv1%2FRoutes%2FDriving%3Fwaypoint.1%3D32.28767%2C34.944118%26waypoint.2%3D32.262513%2C34.859375%26travelMode%3Ddriving%26distanceUnit%3Dmi%26durationUnit%3Dminute%26o%3Djson%26key%3D{API KEY}

Hope it helps!


I thought I posted a reply but not seeing it . 

Just wanted to thanks you @tcnz . It worked !

Hi again Israel,

Any chance you are willing to share the Runkit part of your solution to conver the seconds into Minutes. Never seen Runkit before but looks handy!




exports.endpoint =  function(request, response) {

    var got = require("got");
    var url = require('url');
    var url_parts = url.parse(request.url, true);
    var query = url_parts.query;
    console.log("Key is: " + query.apikey);

    var bingUrl = "https://dev.virtualearth.net/REST/v1/Routes/Driving?waypoint.1=45.627817,-75.724932&waypoint.2=45.637605,-75.918949&travelMode=driving&distanceUnit=mi&durationUnit=minute&key="+ query.apikey;

    console.log("URL to get is: " + bingUrl);
    var result =  got.get(bingUrl).then(result => {
        console.log("Got a valid response: " + JSON.stringify(JSON.parse(result.body).resourceSets[0].resources[0].travelDurationTraffic));
        var obj = {};
        obj.minutes = Math.round(JSON.parse(result.body).resourceSets[0].resources[0].travelDurationTraffic / 60);
    }).catch((err) => {


Then the shieldio url is:

https://img.shields.io/badge/dynamic/json.svg?label=&colorA=purple&colorB=purple&query=$.minutes&style=flat-square&>&suffix=%20minutes&uri=[runkit endpoint with bing apikey]

Many thanks Israel, had never played with Runkit / JS before so its been a fun bit of learning.


Hmm for life of me I can't get that that code to run in RunKit , I get runtime errors

"error": "runtime_error",
  "message": "SyntaxError: Unexpected token ...",
  "stack": [
    "\tgot.stream = (url, options) => got(url, {...options, stream: true});",
    "\t                                         ^^^",

Tried all the 'node' versions of Runkit just in case - real head scratcher.


Bing Maps Travel Time Tile

On the backs of Rob Cummings & Israel Derdik (Cheers guys!), here's a full guide for those wanting to use the free Bing Maps and get time in Minutes/Hours as a tile:

NOTE: it does involve a bit of code, and its overkill purely because Bing ONLY returns travel time in seconds... but its free.

1. Sign Up for a Bing Maps account (https://www.bingmapsportal.com) - Could be an Outlook/hotmail possibly.

2. Click My Account -> My Keys & Generate a Key, save it in a notepad somewhere & treat it as private.

3.Sign Up for a free Runkit Account (https://runkit.com/register)

4. In Runkit, click on the R and select Environment Settings

5. Create an Environment Variable -> Name: bkey ->Value: Paste in your Bing Maps API Key (this is to keep it private and NOT public or provided as a runtime parameter)

6.Click up top right (down arrow) and select My NoteBooks

7. Click the Plus Sign - name the new notebook something

8. Paste in the below code (or visit https://runkit.com/tcnz/bingtraveltime and click Clone up the top)

module.exports.endpoint = async function (request, response){

    var got = require("got");
    const queryString = require('query-string');
    var mySec = process.env.bkey
    const uri = "http://dev.virtualearth.net/REST/v1/Routes/Driving"
    let queryStart = -1;
    let url = request.url;
    let parameters;
    if ((queryStart = request.url.indexOf('?')) > -1) {
        url = url.substring(0, queryStart + 1);
        parameters = queryString.parse(request.url.substring(queryStart + 1));
    var bingURL = uri + "?wp.1=" + parameters.wp1 + "&wp.2=" + parameters.wp2 +     "&optmz=timeWithTraffic&ra=routeSummariesOnly&du=km&o=json&key=" + mySec;

    console.log("URL to get is: " + bingURL);
    var result =  got.get(bingURL).then(result => {
        console.log("Got a valid response: " + JSON.stringify(JSON.parse(result.body).resourceSets[0].resources[0].travelDurationTraffic));

    var obj = {};
    obj.minutes = Math.round(JSON.parse(result.body).resourceSets[0].resources[0].travelDurationTraffic / 60);
    function convertMinsToHrsMins(mins) {
        let h = Math.floor(mins / 60);
        let m = mins % 60;
        h = h < 10 ? '0' + h : h;
        m = m < 10 ? '0' + m : m;
        return `${h}:${m}`;
    var objTime = {
        "travelTime": convertMinsToHrsMins(obj.minutes)
    }).catch((err) => {

8.Click the Endpoint link up the top - This gives you your unique node.js identifier, basically your own little API server.

Now you need your latitude and longitude, 

9. Open Google Maps & type in your starting point for your commute -> Right Click the red flag/pin -> click What's Here, then click the numbers in the bottom of the image (e.g. -37.788034,175.288165)

10. Copy these numbers (the 2nd set like the example in the step above)

11. Repeat the process for your destination

12.Head back to your unique RunKit instance and add this to the end of your url:

/?wp1=(starting coordinates)&wp2=(destination coordinates)
e.g. /?wp1=-37.747198,175.229046&wp2=-37.788034,175.288165

The whole query should look roughly like 


13. Hit Enter and you should see a single line similar to {"travelTime":"00:14"}

14. If it worked, copy the whole URL in the browser

15. Head to shields.io -> Scroll down to the dynamic portion.
In the Datatype drop down - select json
label - call it what you want, e.g. Drive Time
data url - Paste in your working runkit.io URL from step 13/14

16 Hit Make Badge and hopefully you now have your shiny new Shield.io Badge.

From there head to Action Tiles -> My Media -> Add -> This Media is a still image or GIF
Save it and add it to a panel and your done - customization is up to you, but the colors are part of the final shield.io URL so you can tweak them there or re-run the generation step.

Hope it helps!

P.S. If anyone has mad JS skills (this was a first JS project so be kind!), I'd love to try and figure out how to screenshot a webpage and save that as an SVG. The MTG Tile Generator doesn't work for the source site I'm after unfortunately.

Thanks for sharing this fun and detailed example, @tcnz!

As far as I know, "screenshotting" a web page isn't particularly suited to Javascript. You need to find a package (perhaps there are some GitHub projects) that has a pretty sophisticated rendering engine built-in. In other words, there must a be a utility out there that runs on Linux which renders the web page in memory and uses graphic libraries to convert it to an image file. For example, "wget" and "curl" are common Linux utilities which pull down the html text version of a web page - but they don't have the guts to do all the work a full browser does so that an image can be generated.

Offhand, I don't know if any such project exists. I think it is technically possible - e.g., Chrome or Firefox for Linux must somehow render the page over X-Windows or other graphic engines and so the next steps ought to be automatable.

But it will require a server.


Cheers Terry,

You’re spot on, had to use node.js on windows and then used googles headless browser project called Puppeteer.

Takes a screenshot of the size & position you want and saves as a png.

Then had to serve it internally via an existing webserver.

Works a treat!

If Runkit manages to integrate Puppeteer then that could all be pushed to their cloud instancesz

Very cool. 

P.S. Loving ActionTiles, am only a week into the journey but its a great product!

Thanks, tcnz...

I wish this technique were easily scalable, because then ActionTiles could implement it as a service (or recommend a vendor which already offers this...?). Well - we'll keep it in mind. Always happy to hear of creative explorations.

Great stuff !!!

Thanks a lot 

Thanks so much for this. I have a slight problem when I go to the shields.io section. The "Make Badge" button is disabled unless I put something in the query field.

What should go in there?


have you got step 12/13 working and returning the expected time?

If so, copy that whole URL and thats what goes in the “Query” field in Shields.io once JSON is chosen.

Hello, thank you so much for all the details, specially because is my first time trying write a code. The only thing missing is the query that needs to be input on Shields.jo, could someone help me with that?

Hi tcnz, thank you again for the details, but is it possible you to edit the instructions on step 15 and include the "query"?

Thank you 

If anyone is getting stuck on step 15, the Query field should be "travelTime" without quotes.


I'm just here to say thank you to Rob.

I've deployed this tile and it has been an enormous value for my wake up routine, I can check the state of my commute with a single glance to my panel. 


It seems Bing not having the traffic updates .

I checked it for several days and compare it to Waze and no traffic jams in Bing while in Waze it's accurate .

The diff can be 20 minutes between Waze and Bing :-(

I got the travelDurationTraffic and checked also on their site .
Does anyone check that travel duration does align with traffic jams ?

Hi Zvika,

Have double checked mine and it does indeed increase and decrease with traffic for the query I have (see above for examples).

Alas I do have to say though, the commutes I'm monitoring range from 21-40 minutes at most, so there's not a huge fluctuation outside of peak hours, and no motorway to speak of where traffic hits gridlock so your mileage may indeed vary (pun intended).

Google look to possibly have a "free credit" system with their API - I didn't look into it too closely but there may be someone else here who uses their API and gets away with it for free and could be worth switching to?

I'd be keen to know that too and would re-do my setup to utilize Google Maps if its doable. Picking it will depend on how often you poll the route.

Thanks tcnz,

I think Bing not supporting traffic in my country  :-( . I checked L.A and it gives traffic delays .

I hope there is a way to use Waze as from my experience it's the most accurate one .

On Android there is a widget that show the time to work or home depends on the time of day .

Anyway I will check Google .

I will need to refresh it only in the morning from 06:30am - 08:30am every 5 minutes but don't know how to do that in ActionTiles.

Google does have a "free" tier if you're below some crazy amount of requests. You do have to sign up and put in your credit card, but I only get charged $.01 per month. I make calls on this ActionTiles tile and I also check the traffic using Webcore (to set colored lights) and I don't hit their next tier.

Thanks Rob,
how many calls you do ?
Can you share your piston ?

Wow, it looks like I have 5,000 calls in the last 30 days. That's way more that I would have thought. It's probably from Action Tiles refreshing the tile every time we walk by the tablet and wake it up.

Here's my Traffic Light piston... https://community.webcore.co/t/daily-commute-traffic-in-lights/5403

We don't refresh the Tile except per the Refresh Interval.

What is your Refresh Interval?

Every 10 minutes, but the tablet is in the kitchen where there's lot of traffic.

6 calls per hour × 24 hours × 30 days = 4300 calls per month.

Yep, plus the ones my lights use. Are images refreshed exclusively on the schedule or only when the browser calls for the image?

I'm not exactly sure what you are asking, Rob...?

The Media Tile refresh timer only works while a Panel with that Tile is loaded (active) in the browser.


Yep, that answers my question. If no browsers are displaying it, it doesn't get refreshed. It makes sense and that's what I figured. I was just curious how it worked. It's not going to change how I use it. :-)

This is pretty awesome, but goodness me it took a long time for me to figure out how to do this O.o. 


I made a small utility to generate the tile. It wasn't fun editing queries in plain text. It uses Google Maps so you need an API Key.


I have made this work by using a container running windows 7 tiny edition on my nas drive, https://downloadisofile.blogspot.com/p/windows-7-tiny-unattended-fully.html Tiny 7 has a built in web server, an automatic screen grabber with auto crop https://sourceforge.net/projects/autoscreen/

I have firefox with auto refresh running every 1 mins with several tabs, one with google maps and my route to work with traffic, one with my Nissan leaf battery charge status, the auto screen grabs a selected area from each web page tab, drops it in the web server folder as a PNG and smart tiles brings them both in and refreshes every 1 min. works like a charm, in theory you could use this for loads of different web based information

Worked like a charm, but as Rob initially suggested, I would recommend using the Dynamic Generator on the shields.io page. It's output worked the first time.