TomTom Maps
TomTom Maps SDK: interactive maps, search, routing, traffic, geofencing, and real-time location services via Maps SDK for Web and REST APIs
You are an expert in integrating TomTom Maps SDK and APIs for mapping, search, routing, and traffic. ## Key Points - **Routing without `traffic: true`** -- Non-traffic ETAs can be 30%+ off during peak hours. Always enable traffic for any routing that affects user-facing ETAs or operational logistics. - **Forgetting to include the Maps SDK CSS file** -- Without the CSS, markers render without styling, popups are invisible, and map controls do not display correctly. - Use `traffic: true` in routing requests to get realistic ETAs that account for live traffic conditions — the non-traffic ETA can differ significantly during peak hours. - Batch multiple geocoding requests using the batch search API (`/search/2/batch.json`) instead of making individual calls, which reduces latency and counts as fewer transactions. - Set the `language` and `countrySet` parameters in search queries to improve result relevance and reduce ambiguous matches. - The Maps SDK uses `[lng, lat]` order (GeoJSON convention), not `[lat, lng]`. Swapping these produces a map centered in the wrong location or markers placed in the ocean. - Forgetting to include the CSS file for the Maps SDK causes markers and popups to render without styling and controls to be invisible. ## Quick Example ```bash npm install @tomtom-international/web-sdk-maps @tomtom-international/web-sdk-services ```
skilldb get maps-geolocation-services-skills/TomTom MapsFull skill: 213 linesTomTom Maps — Maps & Geolocation
You are an expert in integrating TomTom Maps SDK and APIs for mapping, search, routing, and traffic.
Core Philosophy
TomTom is a mapping company that builds its own map data from ground truth, not a platform that aggregates third-party data. Its core differentiator is real-time traffic intelligence: TomTom collects billions of GPS measurements from vehicles, phones, and infrastructure sensors to produce traffic flow data with high accuracy and low latency. Choose TomTom when traffic-aware routing, real-time traffic visualization, or EV-specific routing with charge station planning are critical requirements.
Always enable traffic in routing requests. The non-traffic ETA can differ from the traffic-aware ETA by 30% or more during peak hours. TomTom's traffic: true parameter uses real-time and historical traffic data to produce realistic arrival times. Routing without traffic data is a guess; routing with it is a prediction based on actual road conditions. For logistics, delivery, and ride-sharing applications, this difference directly impacts customer experience and operational efficiency.
The Maps SDK uses [lng, lat] coordinate order, following the GeoJSON convention. This is the opposite of the common verbal convention ("lat, lng") and the single most frequent source of bugs in TomTom integrations. Every constructor, method, and data structure in the SDK expects longitude first, latitude second. Getting this wrong places markers in the ocean and centers maps on the wrong continent.
Anti-Patterns
- Swapping latitude and longitude in SDK calls -- The Maps SDK uses
[lng, lat]order (GeoJSON convention). Passing[lat, lng]produces a map centered in the wrong location or markers placed in the ocean. - Routing without
traffic: true-- Non-traffic ETAs can be 30%+ off during peak hours. Always enable traffic for any routing that affects user-facing ETAs or operational logistics. - Making individual geocoding calls that could be batched -- TomTom's batch search API (
/search/2/batch.json) processes multiple queries in a single request, reducing latency and counting as fewer transactions against your daily quota. - Forgetting to include the Maps SDK CSS file -- Without the CSS, markers render without styling, popups are invisible, and map controls do not display correctly.
- Not setting
languageandcountrySetin search queries -- Without locale parameters, search results are ambiguous. "Springfield" returns dozens of matches worldwide. SettingcountrySet: "US"andlanguage: "en-US"dramatically improves relevance.
Overview
TomTom provides mapping and location services including interactive vector maps, geocoding/search, routing (with traffic-aware ETA), real-time traffic flow and incidents, geofencing, and EV routing with charge-station planning. The Maps SDK for Web renders vector or raster maps in the browser, while REST APIs serve geocoding, routing, and traffic data. The free tier includes 2,500 daily transactions across most APIs.
Setup & Configuration
API Key
Register at developer.tomtom.com to get an API key.
Maps SDK for Web (npm)
npm install @tomtom-international/web-sdk-maps @tomtom-international/web-sdk-services
import tt from "@tomtom-international/web-sdk-maps";
import ttServices from "@tomtom-international/web-sdk-services";
import "@tomtom-international/web-sdk-maps/dist/maps.css";
const map = tt.map({
key: "YOUR_API_KEY",
container: "map",
center: [13.405, 52.52], // [lng, lat]
zoom: 12,
});
Maps SDK via CDN
<link
rel="stylesheet"
href="https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.25.1/maps/maps.css"
/>
<script src="https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.25.1/maps/maps-web.min.js"></script>
<script src="https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.25.1/services/services-web.min.js"></script>
Core Patterns
Fuzzy Search (Geocoding)
TomTom's search endpoint is called "fuzzy search" and handles addresses, POIs, and categories in a single call.
async function fuzzySearch(query, center) {
const response = await ttServices.services.fuzzySearch({
key: "YOUR_API_KEY",
query,
center,
limit: 5,
language: "en-US",
});
return response.results.map((r) => ({
name: r.poi?.name || r.address.freeformAddress,
position: r.position,
address: r.address,
type: r.type,
}));
}
Reverse Geocoding
async function reverseGeocode(lat, lng) {
const response = await ttServices.services.reverseGeocode({
key: "YOUR_API_KEY",
position: { lat, lng },
});
return response.addresses.map((a) => ({
address: a.address.freeformAddress,
country: a.address.country,
position: a.position,
}));
}
Routing with Traffic
async function calculateRoute(origin, destination) {
const response = await ttServices.services.calculateRoute({
key: "YOUR_API_KEY",
locations: [origin, destination], // each: { lat, lng }
travelMode: "car",
traffic: true,
computeBestOrder: false,
});
const route = response.routes[0];
const summary = route.summary;
return {
distanceMeters: summary.lengthInMeters,
travelTimeSeconds: summary.travelTimeInSeconds,
trafficDelaySeconds: summary.trafficDelayInSeconds,
departureTime: summary.departureTime,
arrivalTime: summary.arrivalTime,
legs: route.legs,
geojson: route.toGeoJson(),
};
}
Displaying a Route on the Map
async function showRoute(map, origin, destination) {
const routeData = await ttServices.services.calculateRoute({
key: "YOUR_API_KEY",
locations: [origin, destination],
travelMode: "car",
traffic: true,
});
const geojson = routeData.toGeoJson();
map.addLayer({
id: "route",
type: "line",
source: { type: "geojson", data: geojson },
paint: {
"line-color": "#4a90d9",
"line-width": 6,
},
});
const bounds = new tt.LngLatBounds();
geojson.features[0].geometry.coordinates.forEach((c) => bounds.extend(c));
map.fitBounds(bounds, { padding: 50 });
}
Traffic Flow
// Add traffic flow layer to the map
function enableTrafficFlow(map) {
map.addTier(
new tt.TrafficFlowTilesTier({
key: "YOUR_API_KEY",
style: "relative", // "absolute", "relative", "relative-delay"
})
);
}
// REST API for a specific road segment
async function getTrafficFlow(lat, lng) {
const url = `https://api.tomtom.com/traffic/services/4/flowSegmentData/relative/10/json?point=${lat},${lng}&key=YOUR_API_KEY`;
const res = await fetch(url);
const data = await res.json();
return {
currentSpeed: data.flowSegmentData.currentSpeed,
freeFlowSpeed: data.flowSegmentData.freeFlowSpeed,
confidence: data.flowSegmentData.confidence,
};
}
Markers and Popups
function addMarkerWithPopup(map, lngLat, popupHtml) {
const popup = new tt.Popup({ offset: 30 }).setHTML(popupHtml);
const marker = new tt.Marker()
.setLngLat(lngLat)
.setPopup(popup)
.addTo(map);
return marker;
}
Best Practices
- Use
traffic: truein routing requests to get realistic ETAs that account for live traffic conditions — the non-traffic ETA can differ significantly during peak hours. - Batch multiple geocoding requests using the batch search API (
/search/2/batch.json) instead of making individual calls, which reduces latency and counts as fewer transactions. - Set the
languageandcountrySetparameters in search queries to improve result relevance and reduce ambiguous matches.
Common Pitfalls
- The Maps SDK uses
[lng, lat]order (GeoJSON convention), not[lat, lng]. Swapping these produces a map centered in the wrong location or markers placed in the ocean. - Forgetting to include the CSS file for the Maps SDK causes markers and popups to render without styling and controls to be invisible.
Install this skill directly: skilldb add maps-geolocation-services-skills
Related Skills
Google Maps Platform
"Google Maps Platform: Maps JavaScript API, Places, Geocoding, Directions, Street View, React (@vis.gl/react-google-maps)"
HERE Maps
HERE Maps Platform: Maps API for JavaScript, geocoding, routing, isoline routing, fleet telematics, and platform data services
Leaflet
"Leaflet: open-source maps, markers, popups, layers, GeoJSON, plugins, React (react-leaflet), tile providers"
Mapbox
"Mapbox: interactive maps, GL JS, geocoding, directions, markers, layers, 3D terrain, React (react-map-gl)"
OpenLayers
OpenLayers: high-performance open-source map library with vector tiles, projections, OGC services (WMS/WFS), drawing interactions, and GeoJSON/KML support
OpenStreetMap & Nominatim
OpenStreetMap tile usage and Nominatim geocoding API: forward/reverse geocoding, tile servers, Overpass API queries, and attribution requirements