Sorry, you need to enable JavaScript to visit this website.

Build a Traffic Alert Dashboard with the TomTom Traffic API

Learn how to build a real-time traffic alert dashboard incorporating the TomTom Traffic API and SDK into a single HTML file, served client-side.


We all face traffic, no matter our differences or unique circumstance — it is one constant that connects us. The more we can avoid traffic, or at least know what to expect before we hit the road, the better.

Luckily, TomTom’s powerful Traffic API provides a real-time endpoint for traffic-related incidents and traffic flow anywhere in the world. Toggle it on or off simply by setting the respective stylesVisibility in any map instance to true or false. 

TomTom reliably sources traffic data from smartphones, commercial fleets, government sensor data, and GPS navigation devices so you can be sure of its accuracy. With over 600 million data sources, TomTom provides accurate overviews of traffic conditions as well as up-to-date information on incidents such as jams, road works, and road closures. The Traffic API adds this information to the Maps SDK display automatically as a layer, including nearby points of interest and a handy location description, such as “near the West Side Mall.”

To illustrate the power and ease-of-use of TomTom’s real-time traffic services, let’s create a seed project for a radio news service’s traffic dashboard. It lists traffic incidents and flow of any place on Earth, with real-time updates, and illustrates this on a map so commuters know what to expect. To do this, we incorporate TomTom’s Traffic API and SDK into a single HTML file, served client-side. 

Let's get started.

Create a Real-Time Traffic Dashboard

To download and run the dashboard yourself, locally, first sign up for a free API key

Adding a basic map to a web page is simple. Follow the instructions in Add TomTom Maps to a Website in 30 Seconds to:

  1. Create a new HTML file in your favorite text editor — let's name the file Traffic.html.
  2. Include the necessary libraries via TomTom’s content delivery network (CDN) (which creates a new tt object).
  3. Create a map using tt.map with the required parameters, key, and container.
  4. Create a div to contain the map using the container id — “map” in our case.

Because we want our dashboard to be initialized for a user-defined city, we’re going to do things a little differently from the above example. However, the basic steps are the same. 

Include the following libraries inside the <head> tag of “Traffic.html”.

●JavaScript

https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.5.0/maps/maps-web.min.js

https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.6.0/services/services-web.min.js

●CSS

https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.5.0/maps/maps.css

Paste the following JavaScript inside a <script> tag.

var key = "[YOUR_KEY]";

function makeMap(result) {
  var coor = result['results'][0]['position'];
  var lnglat = [coor['lng'], coor['lat']];
  const map = tt.map({
      key: key,
      container: "map",
      stylesVisibility: {
            trafficIncidents: true,
            trafficFlow: true
      },
      center: lnglat, //lng,lat
      zoom:13,
  });
  getIncidents(map.getBounds());
};


const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const city = urlParams.get('city');
document.getElementById('city-header').innerHTML = "Current Traffic Incidents in "+city;
tt.services.geocode({
      key: key,
      query: city,
}).then(makeMap);

At the top, create a variable to hold your API key and paste it there.

var key = "[YOUR_KEY]";

Because we’re creating our map with a user-defined city, let’s define the city in a URL parameter called “city” and store it in a const. Also, we’ll create an HTML header with #city-header in the next step, but you can set its hypothetical value now. 

const city = urlParams.get('city');

document.getElementById('city-header').innerHTML = "Current Traffic Incidents in "+city;

Next, call tt.services.geocode with your key and city variables to geocode the query. Finally, redirect the result to a function we’ll call makeMap.

This initial step captures a URL parameter, stores the text in a variable, and geocodes it for map initialization.

Initialize the Map

Now, let’s initialize the map.

function makeMap(result) {
  var coor = result['results'][0]['position'];
  var lnglat = [coor['lng'], coor['lat']];
  const map = tt.map({
      key: key,
      container: "map",
      stylesVisibility: {
            trafficIncidents: true,
            trafficFlow: true
      },
      center: lnglat, //lng,lat
      zoom:13,
  });
  getIncidents(map.getBounds());
};

The geocode callback returns a coordinates object. With it, we can center the map on the place defined in the URL parameter, but first we need to arrange it in a “lng,lat” string orientation.

var coor = result['results'][0]['position'];

var lnglat = [coor['lng'], coor['lat']];

Now, we initialize the map using tt.map. Inside it, add your API key, define an HTML container called #map, set the stylesVisibility for incidents and flow to true, center the map on lnglat, and set an initial zoom to 13.

That’s it. We now have the JavaScript to initialize a URL-defined city map. 

Connect to Traffic API

Finally, call a new function getIncidents with a map.getBounds argument. This gives us the information we need to make a request to the Traffic API using the existing map’s bounds. 

Below the first call to tt.services.geocode, paste the following JavaScript:

var xmlhttp = new XMLHttpRequest();

function reqListener () {
      var arr = JSON.parse(this.responseText)['tm']['poi'];
      var txt = "<tr><th>From</th><th>Description</th><th>Cause</th></tr>";
      arr.forEach(function(obj){
            var icd = ic[obj['ic']];
            var tyd = ty[obj['ty']];
            txt += "<tr style='background-color:"+tyd[1]+"'><td>"+obj['f']+"</td><td>"+obj['d']+"</td><td style='width:20%;'>"+icd+"</td></tr>";

      });
      document.getElementById('tabledata').innerHTML = txt;
}

function getIncidents(bounds){
      var bounds_arr = [bounds['_sw']['lat'],bounds['_sw']['lng'],bounds['_ne']['lat'],bounds['_ne']['lng']];

      var query = "https://api.tomtom.com/traffic/services/4/incidentDetails/s3/"+bounds_arr.join()+"/13/-1/json?projection=EPSG4326&key="+key;

      xmlhttp.addEventListener("load", reqListener);
      xmlhttp.open("GET", query, true);
      xmlhttp.send();
};

To make an API request, first create a new XMLHttpRequest.

Skip over the reqListener function, which handles our request, and let’s take a look at the getIncidents function.

The first thing we need to do is parse the map bounds into an acceptable format for the traffic API. Let’s choose an EPSG4326 projection, which requires a “sw_lat,sw_lng,ne_lat,ne_lng” orientation for the coordinate bounds.

Next, construct the URL request for the traffic incident details endpoint, ensuring you pass the same zoom level to the request used in your map, and return the data in a JSON format.

var bounds_arr = [bounds['_sw']['lat'],bounds['_sw']['lng'],bounds['_ne']['lat'],bounds['_ne']['lng']];

var query = "https://api.tomtom.com/traffic/services/4/incidentDetails/s3/"+bounds_arr.join()+"/13/-1/json?projection=EPSG4326&key="+key;

Finally, make the request using xmlhttp, and add an event listener to handle the request.

The reqListener function parses the returned call into an array and creates a .txt variable with table headers to iteratively update an HTML table.

The API request returns a lot of information. For our example, we’re only going to use four headers.

●<ty>: The delay magnitude.

●<f>: The name of the intersection or location where the traffic due to the incident starts.

●<d>: Description of the incident.

●<ic>: The icon category associated with this incident.

Both <ic> and <ty> are represented as codes, so to make them human-readable we need their values. For <ty> — the incident magnitude — especially, it might be more useful to color code the incidents, for a more effective visualization.

Below the <script> tag, paste the following objects: 

var ic = {
      0: 'Unknown',
      1: 'Accident',
      2: 'Fog',
      3: 'Dangerous Conditions',
      4: 'Rain',
      5: 'Ice',
      6: 'Jam',
      7: 'Lane Closed',
      8: 'Road Closed',
      9: 'Road Works',
      10: 'Wind',
      11: 'Flooding',
      12: 'Detour',
      13: 'Cluster',
      14: 'Broken Down Vehicle',
}

var ty = {
      0: ['Unknown','rgba(0,0,0,0.25)'],
      1: ['Minor','rgba(0,153,0,0.25)'],
      2: ['Moderate','rgba(255,102,0,0.25)'],
      3: ['Major','rgba(255,0,0,0.25)'],
      4: ['Undefined','rgba(102,204,255,0.25)']
}

As we iterate the array, we can now convert <ic> and <ty> data points into more user-friendly formats. 

Once the iteration is complete, set the value of #tabledata to txt.

Format the Dashboard

All that’s left is to add some basic HTML and CSS, then we’re all set to view our creation. 

Paste the following, including the new <body> tag right after your <head> tag.

<body style="height:100%;margin: 0; padding: 0;">
  <div style="display: grid;grid-template-columns: 25% 75%;height:100%;">
      <div class="row" style="max-height:100%;overflow-y:scroll;">
        <center>
          <h1 id="city-header" style="padding: 5px;"></h1>
            <ul id="legend">
         <li style="background-color: rgba(0,0,0,0.25);">Unknown</li>
         <li style="background-color: rgba(0,153,0,0.25);">Minor</li>
         <li style="background-color: rgba(255,102,0,0.25);">Moderate</li>
         <li style="background-color: rgba(255,0,0,0.25);">Major</li>
         <li style="background-color: rgba(102,204,255,0.25);">Undefined</li>
        </ul> 
      </center>
      <table id="tabledata"></table>
    </div>
    <div id="map" style="height: 100%;"></div>
  </div>

 Paste this style inside the <head> tag.

<style type="text/css">th {text-align:left;} table {table-layout: fixed;} td {width: 40%;padding:5px;} ul#legend li {display: inline;padding:2px;}</style>

Now all we have to do is save and run it!

Results

Open the file in your favourite browser (we tested in Chrome) and give the URL a city parameter. We chose New York City for our test.

?city=New%20York%20City

image1

You now have a dashboard with real-time traffic information and nearby points of interest.

The source code can be found here.

Next Steps

We hope this project template gets you off to a good start to solving one of the most pervasive problems connecting us all — traffic! You now know how to quickly and easily create a map dashboard by incorporating TomTom’s APIs into an HTML document.

To expand on this project, consider adding a focus feature to table rows, or a details column which could allow users to explore more of the information returned from the API request. Your news app users will appreciate the real-time traffic information to help them get where they need to go.

Check out the Traffic Index for TomTom’s insights on traffic congestion levels. Want to create your own traffic dashboard? Become a TomTom developer

Here's a YouTube video overview of how to add traffic layers in the TomTom SDK for Web v6, with Product Marketing Manager Jonathan Americo:

Lastly, here are some suggested related articles:

Happy mapping!

First published: 
Tuesday, March 23, 2021 - 20:12
Last edited: 
Thursday, March 25, 2021 - 20:21