How to Create Google Maps with Several Locations

Google Maps With Several Locations: How to Create a Professional Multi-Point Map for Your Website

Need to display multiple business locations, event venues, or project sites on Google Maps? While embedding a single location is straightforward, creating a custom map with several locations requires technical implementation. This guide will walk you through building an interactive, filterable multi-location map using the Google Maps Platform.

Method: Building a Filterable Multi-Location Map with Custom Controls

This solution creates a professional business location finder with category filters—ideal for companies with multiple store types or service areas.

Step 1: API Setup & Data Structure

First, you need to enable the Google Maps JavaScript API in Google Cloud Console and create an API key with proper restrictions. This requires a Google Cloud account with billing enabled.

Now, structure your location data with categories for filtering:

javascript

// locations.js - Save this as a separate file
const businessLocations = [
    {
        id: 1,
        name: "Downtown Café",
        address: "123 Main St, New York, NY",
        position: { lat: 40.7128, lng: -74.0060 },
        category: "cafe",
        hours: "7AM-8PM",
        phone: "(555) 123-4567",
        features: ["WiFi", "Outdoor Seating", "Takeout"]
    },
    {
        id: 2,
        name: "Uptown Restaurant",
        address: "456 Park Ave, New York, NY",
        position: { lat: 40.7794, lng: -73.9632 },
        category: "restaurant",
        hours: "11AM-11PM",
        phone: "(555) 987-6543",
        features: ["Fine Dining", "Reservations", "Bar"]
    },
    {
        id: 3,
        name: "West Side Coffee Shop",
        address: "789 Broadway, New York, NY",
        position: { lat: 40.7336, lng: -74.0000 },
        category: "cafe",
        hours: "6AM-7PM",
        phone: "(555) 456-7890",
        features: ["WiFi", "Coffee Roasting", "Pastries"]
    },
    {
        id: 4,
        name: "Central Bakery",
        address: "321 5th Ave, New York, NY",
        position: { lat: 40.7489, lng: -73.9850 },
        category: "bakery",
        hours: "8AM-6PM",
        phone: "(555) 234-5678",
        features: ["Fresh Bread", "Catering", "Gluten-Free"]
    }
];Code language: JavaScript (javascript)

Structured location data with categories, hours, and features for filtering

Step 2: Create the Interactive Map Interface

This HTML file creates a complete location finder with category filters and detailed info windows:

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Business Locations Map</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            line-height: 1.6;
            color: #333;
        }
        
        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
        }
        
        header {
            text-align: center;
            margin-bottom: 30px;
            padding-bottom: 20px;
            border-bottom: 1px solid #eee;
        }
        
        h1 {
            color: #1a73e8;
            margin-bottom: 10px;
        }
        
        .subtitle {
            color: #666;
            font-size: 1.1rem;
        }
        
        .app-layout {
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        
        @media (min-width: 992px) {
            .app-layout {
                flex-direction: row;
            }
        }
        
        .sidebar {
            flex: 1;
            background: #f8f9fa;
            border-radius: 12px;
            padding: 25px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.05);
        }
        
        .map-container {
            flex: 2;
            border-radius: 12px;
            overflow: hidden;
            box-shadow: 0 4px 20px rgba(0,0,0,0.1);
        }
        
        #map {
            height: 600px;
            width: 100%;
        }
        
        .filter-section {
            margin-bottom: 25px;
        }
        
        .filter-title {
            font-weight: 600;
            margin-bottom: 15px;
            color: #444;
            font-size: 1.1rem;
        }
        
        .filter-buttons {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
        }
        
        .filter-btn {
            padding: 8px 16px;
            background: white;
            border: 2px solid #ddd;
            border-radius: 20px;
            cursor: pointer;
            font-weight: 500;
            transition: all 0.2s ease;
        }
        
        .filter-btn:hover {
            border-color: #1a73e8;
            color: #1a73e8;
        }
        
        .filter-btn.active {
            background: #1a73e8;
            color: white;
            border-color: #1a73e8;
        }
        
        .locations-list {
            max-height: 400px;
            overflow-y: auto;
        }
        
        .location-card {
            background: white;
            padding: 15px;
            margin-bottom: 15px;
            border-radius: 8px;
            border-left: 4px solid #1a73e8;
            cursor: pointer;
            transition: transform 0.2s ease;
        }
        
        .location-card:hover {
            transform: translateX(5px);
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
        }
        
        .location-name {
            font-weight: 600;
            color: #1a73e8;
            margin-bottom: 5px;
        }
        
        .location-category {
            display: inline-block;
            padding: 3px 10px;
            background: #e8f0fe;
            color: #1a73e8;
            border-radius: 12px;
            font-size: 0.8rem;
            margin-bottom: 10px;
        }
        
        .info-window-content {
            padding: 10px;
            max-width: 250px;
        }
        
        .info-title {
            font-weight: 600;
            color: #1a73e8;
            margin-bottom: 5px;
            font-size: 1.1rem;
        }
        
        .info-features {
            margin-top: 10px;
            font-size: 0.9rem;
        }
        
        .feature-tag {
            display: inline-block;
            background: #f1f3f4;
            padding: 3px 8px;
            border-radius: 10px;
            margin: 2px;
            font-size: 0.8rem;
        }
        
        .no-results {
            text-align: center;
            padding: 20px;
            color: #666;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>Find Our Locations</h1>
            <p class="subtitle">Browse all our stores and filter by category</p>
        </header>
        
        <div class="app-layout">
            <div class="sidebar">
                <div class="filter-section">
                    <div class="filter-title">Filter by Category</div>
                    <div class="filter-buttons" id="category-filters">
                        <button class="filter-btn active" data-category="all">All Locations</button>
                        <button class="filter-btn" data-category="cafe">Cafés</button>
                        <button class="filter-btn" data-category="restaurant">Restaurants</button>
                        <button class="filter-btn" data-category="bakery">Bakeries</button>
                    </div>
                </div>
                
                <div class="filter-section">
                    <div class="filter-title">Features</div>
                    <div class="filter-buttons" id="feature-filters">
                        <button class="filter-btn" data-feature="WiFi">WiFi</button>
                        <button class="filter-btn" data-feature="Outdoor Seating">Outdoor</button>
                        <button class="filter-btn" data-feature="Takeout">Takeout</button>
                        <button class="filter-btn" data-feature="Reservations">Reservations</button>
                    </div>
                </div>
                
                <div class="locations-list" id="locations-list">
                    <!-- Dynamic content will be loaded here -->
                </div>
            </div>
            
            <div class="map-container">
                <div id="map"></div>
            </div>
        </div>
    </div>

    <!-- Include Google Maps with your API Key -->
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY_HERE&callback=initMap" async defer></script>
    
    <!-- Include the locations data -->
    <script src="locations.js"></script>
    
    <script>
        let map;
        let markers = [];
        let activeCategory = 'all';
        let activeFeatures = [];
        
        function initMap() {
            // Initialize the map
            map = new google.maps.Map(document.getElementById('map'), {
                zoom: 12,
                center: { lat: 40.7128, lng: -74.0060 }, // NYC
                styles: [
                    {
                        featureType: 'poi.business',
                        stylers: [{ visibility: 'off' }]
                    }
                ]
            });
            
            // Load all locations initially
            loadLocations();
            setupEventListeners();
        }
        
        function loadLocations() {
            // Clear existing markers
            markers.forEach(marker => marker.setMap(null));
            markers = [];
            
            // Filter locations based on active filters
            const filteredLocations = businessLocations.filter(location => {
                // Category filter
                if (activeCategory !== 'all' && location.category !== activeCategory) {
                    return false;
                }
                
                // Feature filters
                if (activeFeatures.length > 0) {
                    const hasAllFeatures = activeFeatures.every(feature => 
                        location.features.includes(feature)
                    );
                    if (!hasAllFeatures) return false;
                }
                
                return true;
            });
            
            // Display in list
            displayLocationList(filteredLocations);
            
            // Add markers to map
            filteredLocations.forEach(location => {
                const marker = new google.maps.Marker({
                    position: location.position,
                    map: map,
                    title: location.name,
                    icon: getMarkerIcon(location.category)
                });
                
                // Create info window
                const infoWindow = new google.maps.InfoWindow({
                    content: createInfoWindowContent(location)
                });
                
                marker.addListener('click', () => {
                    infoWindow.open(map, marker);
                });
                
                // Add click listener to list item
                const listItem = document.querySelector(`[data-location-id="${location.id}"]`);
                if (listItem) {
                    listItem.addEventListener('click', () => {
                        map.setZoom(16);
                        map.setCenter(marker.getPosition());
                        infoWindow.open(map, marker);
                    });
                }
                
                markers.push(marker);
            });
            
            // Adjust map bounds if markers exist
            if (filteredLocations.length > 0) {
                const bounds = new google.maps.LatLngBounds();
                filteredLocations.forEach(location => {
                    bounds.extend(location.position);
                });
                map.fitBounds(bounds, { padding: 50 });
            }
        }
        
        function getMarkerIcon(category) {
            // Custom icons for different categories
            const icons = {
                cafe: {
                    url: 'https://maps.google.com/mapfiles/ms/icons/blue-dot.png'
                },
                restaurant: {
                    url: 'https://maps.google.com/mapfiles/ms/icons/red-dot.png'
                },
                bakery: {
                    url: 'https://maps.google.com/mapfiles/ms/icons/green-dot.png'
                }
            };
            
            return icons[category] || icons.cafe;
        }
        
        function createInfoWindowContent(location) {
            return `
                <div class="info-window-content">
                    <div class="info-title">${location.name}</div>
                    <div><strong>Address:</strong> ${location.address}</div>
                    <div><strong>Hours:</strong> ${location.hours}</div>
                    <div><strong>Phone:</strong> ${location.phone}</div>
                    <div class="info-features">
                        ${location.features.map(feature => 
                            `<span class="feature-tag">${feature}</span>`
                        ).join('')}
                    </div>
                </div>
            `;
        }
        
        function displayLocationList(locations) {
            const container = document.getElementById('locations-list');
            
            if (locations.length === 0) {
                container.innerHTML = '<div class="no-results">No locations match your filters</div>';
                return;
            }
            
            container.innerHTML = locations.map(location => `
                <div class="location-card" data-location-id="${location.id}">
                    <div class="location-name">${location.name}</div>
                    <div class="location-category">${location.category.toUpperCase()}</div>
                    <div><strong>Address:</strong> ${location.address}</div>
                    <div><strong>Hours:</strong> ${location.hours}</div>
                    <div><strong>Phone:</strong> ${location.phone}</div>
                    <div class="info-features" style="margin-top: 8px;">
                        ${location.features.map(feature => 
                            `<span class="feature-tag">${feature}</span>`
                        ).join('')}
                    </div>
                </div>
            `).join('');
        }
        
        function setupEventListeners() {
            // Category filter buttons
            document.querySelectorAll('#category-filters .filter-btn').forEach(btn => {
                btn.addEventListener('click', () => {
                    document.querySelectorAll('#category-filters .filter-btn').forEach(b => {
                        b.classList.remove('active');
                    });
                    btn.classList.add('active');
                    activeCategory = btn.dataset.category;
                    loadLocations();
                });
            });
            
            // Feature filter buttons
            document.querySelectorAll('#feature-filters .filter-btn').forEach(btn => {
                btn.addEventListener('click', () => {
                    btn.classList.toggle('active');
                    const feature = btn.dataset.feature;
                    
                    if (btn.classList.contains('active')) {
                        activeFeatures.push(feature);
                    } else {
                        activeFeatures = activeFeatures.filter(f => f !== feature);
                    }
                    
                    loadLocations();
                });
            });
        }
    </script>
</body>
</html>
Code language: HTML, XML (xml)

Professional multi-location finder with category filters, detailed cards, and custom map markers.

Step 3: Challenges You’ll Face

Despite creating a polished map, you’ll encounter several ongoing challenges:

  • 1.  API Management: Google Maps Platform requires constant key monitoring, quota management, and cost control
  • 2.  Data Synchronization: Every location change requires code deployment
  • 3.  Mobile Responsiveness: Ensuring filters work perfectly on all devices adds complexity
  • 4.  Performance Issues: Loading many markers can slow down your website
  • 5.  Maintenance Burden: Google regularly updates their APIs, requiring code updates

Create Multi-Location Maps in Minutes, Not Weeks

What if you could have this same professional, filterable multi-location map without any coding, API management, or technical headaches?

MapsFun.com provides all the functionality of the complex solution above, plus more:

  • 1.  Visual Map Editor: Add and edit locations directly on the map—no code changes needed
  • 2.  Smart Filtering: Create category filters with point-and-click interface
  • 3.  Automatic Updates: Change hours, phone numbers, or add new locations instantly
  • 4.  No API Limits: Handle hundreds of locations without performance issues
  • 5.  Built-in Analytics: See how visitors interact with your map

Stop spending weeks building and maintaining custom map solutions. Create a better multi-location Google Map in minutes—visit MapsFun.com to get started for free.