Widget Integration Guide

Learn how to integrate the Global Device Network map into your website

Prerequisites

Before you begin, you'll need:
  • A Mapbox account and access token (get one at mapbox.com)
  • Basic understanding of HTML and JavaScript
  • A website where you want to embed the map
  • Optional: An API endpoint that returns device data in the required format

Integration Options

There are two ways to integrate the map widget:
  1. Static Data Integration: Use this when you have a fixed set of devices or want to hardcode the device data.
  2. API Integration: Use this when you want to fetch device data dynamically from your backend.

Option 1: Static Data Integration

Use this approach when you want to display a fixed set of devices:
<!-- Add this in your HTML head -->
<link href="https://api.mapbox.com/mapbox-gl-js/v3.13.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v3.13.0/mapbox-gl.js"></script>

<!-- Add this where you want the map to appear -->
<div id="device-map" style="width: 100%; height: 500px;"></div>

<!-- Add this script after your map container -->
<script>
  (function() {
    // Replace with your Mapbox access token
    const MAPBOX_ACCESS_TOKEN = 'YOUR_MAPBOX_ACCESS_TOKEN';
    
    // Replace this with your actual device data
    const deviceData = [
  {
    "city": "San Francisco",
    "country": "USA",
    "lat": 37.7749,
    "lng": -122.4194,
    "total": 2
  },
  {
    "city": "New York",
    "country": "USA",
    "lat": 40.7128,
    "lng": -74.006,
    "total": 3
  },
  {
    "city": "London",
    "country": "UK",
    "lat": 51.5074,
    "lng": -0.1278,
    "total": 2
  }
];

    // Initialize map
    mapboxgl.accessToken = MAPBOX_ACCESS_TOKEN;
    const map = new mapboxgl.Map({
      container: 'device-map',
      style: 'mapbox://styles/mapbox/dark-v11',
      center: [15, 50],
      zoom: 4,
      attributionControl: false
    });

    // Add custom styling when map loads
    map.on('style.load', () => {
      map.setFog({
        'color': '#1a1f2e',
        'high-color': '#080C16',
        'horizon-blend': 0.3,
        'space-color': '#080C16',
        'star-intensity': 0.6
      });

      map.setPaintProperty('water', 'fill-color', '#1a1f2e');
      map.setPaintProperty('background', 'background-color', '#3d4555');
      map.setPaintProperty('land', 'background-color', '#3d4555');
      map.setPaintProperty('land', 'fill-extrusion-height', 1);
      map.setPaintProperty('land', 'fill-extrusion-opacity', 0.8);
      map.setPaintProperty('admin-0-boundary', 'line-color', '#5a6577');
      map.setPaintProperty('admin-0-boundary', 'line-width', 1);
    });

    // Add markers for each device
    deviceData.forEach(device => {
      const markerEl = document.createElement('div');
      markerEl.className = 'custom-marker';
      markerEl.innerHTML = `<div class="marker-content">${device.total}</div>`;

      const popup = new mapboxgl.Popup({
        offset: 25,
        closeButton: false,
        className: 'custom-popup'
      })
        .setHTML(`
          <div class="popup-content">
            <h3>${device.city}, ${device.country} <span class="pulse-dot">•</span></h3>
            <div class="popup-details">
              Total ${device.total === 1 ? 'Device' : 'Devices'}: <b>${device.total}</b>
            </div>
          </div>
        `);

      new mapboxgl.Marker(markerEl)
        .setLngLat([device.lng, device.lat])
        .setPopup(popup)
        .addTo(map);
    });
  })();
</script>

Option 2: API Integration

Use this approach when you want to fetch device data dynamically from your API:
<!-- Add this in your HTML head -->
<link href="https://api.mapbox.com/mapbox-gl-js/v3.13.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v3.13.0/mapbox-gl.js"></script>

<!-- Add this where you want the map to appear -->
<div id="device-map" style="width: 100%; height: 500px;"></div>

<!-- Add this script after your map container -->
<script>
  (function() {
    // Configuration
    const API_CONFIG = {
      DEVICES_ENDPOINT: '/api/devices'  // Replace with your API endpoint
    };
    const MAPBOX_ACCESS_TOKEN = 'YOUR_MAPBOX_ACCESS_TOKEN';

    // Function to fetch device data
    async function getDevices() {
      try {
        const response = await fetch(API_CONFIG.DEVICES_ENDPOINT);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        return await response.json();
      } catch (error) {
        console.error('Error fetching device data:', error);
        // Optionally return sample data as fallback
        return [
  {
    "city": "San Francisco",
    "country": "USA",
    "lat": 37.7749,
    "lng": -122.4194,
    "total": 2
  },
  {
    "city": "New York",
    "country": "USA",
    "lat": 40.7128,
    "lng": -74.006,
    "total": 3
  },
  {
    "city": "London",
    "country": "UK",
    "lat": 51.5074,
    "lng": -0.1278,
    "total": 2
  }
];
      }
    }

    // Initialize map with API data
    async function initializeMap() {
      // Get device data
      const deviceData = await getDevices();
      
      // Initialize map
      mapboxgl.accessToken = MAPBOX_ACCESS_TOKEN;
      const map = new mapboxgl.Map({
        container: 'device-map',
        style: 'mapbox://styles/mapbox/dark-v11',
        center: [15, 50],
        zoom: 4,
        attributionControl: false
      });

      // Add custom styling when map loads
      map.on('style.load', () => {
        map.setFog({
          'color': '#1a1f2e',
          'high-color': '#080C16',
          'horizon-blend': 0.3,
          'space-color': '#080C16',
          'star-intensity': 0.6
        });

        map.setPaintProperty('water', 'fill-color', '#1a1f2e');
        map.setPaintProperty('background', 'background-color', '#3d4555');
        map.setPaintProperty('land', 'background-color', '#3d4555');
        map.setPaintProperty('land', 'fill-extrusion-height', 1);
        map.setPaintProperty('land', 'fill-extrusion-opacity', 0.8);
        map.setPaintProperty('admin-0-boundary', 'line-color', '#5a6577');
        map.setPaintProperty('admin-0-boundary', 'line-width', 1);
      });

      // Add markers for each device
      deviceData.forEach(device => {
        const markerEl = document.createElement('div');
        markerEl.className = 'custom-marker';
        markerEl.innerHTML = `<div class="marker-content">${device.total}</div>`;

        const popup = new mapboxgl.Popup({
          offset: 25,
          closeButton: false,
          className: 'custom-popup'
        })
          .setHTML(`
            <div class="popup-content">
              <h3>${device.city}, ${device.country} <span class="pulse-dot">•</span></h3>
              <div class="popup-details">
                Total ${device.total === 1 ? 'Device' : 'Devices'}: <b>${device.total}</b>
              </div>
            </div>
          `);

        new mapboxgl.Marker(markerEl)
          .setLngLat([device.lng, device.lat])
          .setPopup(popup)
          .addTo(map);
      });
    }

    // Initialize the map
    initializeMap().catch(console.error);
  })();
</script>

API Response Format

Your API endpoint should return an array of device objects in the following format:
[
  {
    city: string,    // City name
    country: string, // Country name
    lat: number,     // Latitude
    lng: number,     // Longitude
    total: number    // Number of devices
  }
]

Customization

You can customize the widget by modifying the following:
  • Map style: Change mapbox://styles/mapbox/dark-v11 to any other Mapbox style
  • Initial view: Adjust center and zoom values
  • Marker colors: Modify the CSS for .marker-content
  • Popup design: Customize the CSS for .mapboxgl-popup-content
  • API endpoint: Configure your own endpoint in API_CONFIG.DEVICES_ENDPOINT
  • Error handling: Modify the fallback behavior in the getDevices function

Need Help?

For additional support or feature requests, please: