La maggior parte dei prodotti di local discovery vive o muore su una sola schermata: la mappa. Un utente apre la tua app per rispondere a una domanda semplice, cosa c'è vicino a me in questo momento, e la mappa è il modo in cui trova la risposta. Realizzare bene quella mappa, con i pin giusti, un filtraggio veloce e annunci che i motori di ricerca possono davvero leggere, è il cuore del lavoro ingegneristico dietro qualsiasi guida agli eventi.
Questa guida illustra la creazione di una mappa degli eventi cittadini da zero: modellare i dati dell'evento, geocodificare i locali in coordinate, posizionare e raggruppare i marker, filtrare per categoria e quartiere e rendere gli annunci individuabili. Si presuppone che tu sappia già come renderizzare una mappa di base. Se non è così, parti dal nostro tutorial su come aggiungere mappe interattive al tuo sito web e torna qui per le parti specifiche degli eventi.
Modella l'evento intorno al suo locale
Un evento è qualcosa di delimitato nel tempo che accade in un luogo. Il luogo è ciò che finisce sulla mappa, quindi il locale è l'ancora del tuo modello dati. Un record di evento minimo si presenta così:
const event = {
id: 'evt_8471',
title: 'Late Night Jazz at The Vortex',
category: 'live-music',
venue: 'The Vortex Jazz Club, 11 Gillett Square, London N16 8AZ',
coords: null, // popolato dal geocoding, una volta sola
neighbourhood: null, // popolato dal reverse geocoding, una volta sola
startsAt: '2026-07-09T20:30:00Z',
url: 'https://example.com/tickets/8471',
};
I due campi null contano. Non vuoi geocodificare un locale ogni volta che la mappa si carica. Geocodifica una sola volta, quando l'evento viene creato o importato, poi memorizza le coordinate e trattale come permanenti.
Passo 1: geocodifica ogni locale in coordinate
Il geocoding trasforma un indirizzo leggibile dalle persone in una latitudine e una longitudine che puoi posizionare. Invia la stringa del locale alla Geocoding API e leggi le coordinate dal primo risultato:
async function geocodeVenue(address) {
const url = new URL('https://api.mapatlas.eu/geocoding/v1/search');
url.searchParams.set('text', address);
url.searchParams.set('size', '1');
const res = await fetch(url, { headers: { Authorization: `Bearer ${API_KEY}` } });
const data = await res.json();
const top = data.features?.[0];
if (!top) return null;
const [lon, lat] = top.geometry.coordinates;
return { lat, lon, label: top.properties.label };
}
Esegui questa operazione in fase di scrittura, quando un evento entra nel tuo sistema, e persisti le coordinate restituite sul record. Per una spiegazione completa del perché la posizione esatta del pin conta, e di come le coordinate del tetto differiscono dalla porta a cui le persone arrivano davvero, vedi il geocoding dell'ingresso degli edifici.
Passo 2: posiziona gli eventi come marker
Con le coordinate su ogni evento, posizionarli è un ciclo. Assegna a ogni categoria il proprio colore, così la mappa si legge a colpo d'occhio:
const CATEGORY_COLORS = {
'live-music': '#E75480',
'theatre': '#006BA6',
'comedy': '#EE7C0E',
'food': '#16A34A',
'nightlife': '#7C3AED',
};
function plotEvents(map, events) {
events.forEach((evt) => {
if (!evt.coords) return;
const popup = new mapmetricsgl.Popup().setHTML(
`<strong>${evt.title}</strong><br>${new Date(evt.startsAt).toLocaleString()}` +
`<br><a href="${evt.url}">Biglietti</a>`,
);
new mapmetricsgl.Marker({ color: CATEGORY_COLORS[evt.category] || '#0c3456' })
.setLngLat([evt.coords.lon, evt.coords.lat])
.setPopup(popup)
.addTo(map);
});
}
Questo è il pattern dietro prodotti reali. Un esempio dal vivo è OnlyHere, una guida quotidiana alle cose da fare a Londra che geocodifica ogni locale e posiziona gli eventi della giornata su una mappa interattiva MapAtlas, così l'utente può esplorare cosa c'è per locale e quartiere invece di scorrere una lista piatta.
Passo 3: raggruppa quando la città si riempie
I singoli marker vanno bene per una manciata di eventi. Un feed cittadino non è una manciata. Non appena superi circa 100 o 200 pin, sposta gli eventi in una sorgente GeoJSON e lascia che la mappa li raggruppi:
map.addSource('events', {
type: 'geojson',
cluster: true,
clusterRadius: 50,
data: {
type: 'FeatureCollection',
features: events.filter((e) => e.coords).map((e) => ({
type: 'Feature',
geometry: { type: 'Point', coordinates: [e.coords.lon, e.coords.lat] },
properties: { title: e.title, category: e.category },
})),
},
});
Ora una serata movimentata nel centro città mostra una singola bolla con un contatore invece di cento pin sovrapposti, e il cluster si separa man mano che l'utente ingrandisce.
Passo 4: filtra per categoria e quartiere
È il filtraggio che trasforma una mappa degli eventi in un prodotto di eventi. Tieni l'elenco completo in memoria e filtra l'array, poi consegna l'insieme filtrato alla sorgente della mappa invece di ricostruire i marker a mano:
function applyFilters(map, allEvents, { category, neighbourhood }) {
const filtered = allEvents.filter((e) =>
(!category || e.category === category) &&
(!neighbourhood || e.neighbourhood === neighbourhood),
);
map.getSource('events').setData({
type: 'FeatureCollection',
features: filtered.filter((e) => e.coords).map((e) => ({
type: 'Feature',
geometry: { type: 'Point', coordinates: [e.coords.lon, e.coords.lat] },
properties: { title: e.title },
})),
});
return filtered;
}
Per popolare il campo neighbourhood, applica una volta il reverse geocoding alle coordinate di ogni locale e memorizza il nome dell'area amministrativa. Questo singolo valore alimenta un menu a tendina dei quartieri, una vista "cosa c'è in questa zona" e una pagina di annunci più pulita, tutto senza un'altra chiamata a runtime.
Passo 5: rendi gli annunci individuabili
Una mappa risponde alla domanda per la persona già dentro la tua app. Non fa nulla per il pubblico molto più ampio che chiede a un motore di ricerca o a un assistente IA "cosa c'è stasera a Shoreditch". Quei sistemi leggono dati strutturati, non pixel.
Marca ogni evento con i campi Event di schema.org e riutilizza le coordinate che hai già:
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Late Night Jazz at The Vortex",
"startDate": "2026-07-09T20:30:00Z",
"location": {
"@type": "Place",
"name": "The Vortex Jazz Club",
"geo": { "@type": "GeoCoordinates", "latitude": 51.5462, "longitude": -0.0753 }
}
}
Le coordinate che disegnano il pin alimentano anche i dati strutturati, così visualizzazione e scoperta provengono da un'unica fonte di verità. Questa è la differenza tra una mappa che appare bene e un prodotto che viene trovato. Per approfondire perché i dati di localizzazione leggibili dalle macchine aumentano la visibilità nella ricerca IA, consulta la nostra guida alle FAQ specifiche per località per la ricerca IA.
Mettere tutto insieme
Una mappa degli eventi cittadini è fatta di cinque componenti mobili: un modello dati ancorato al locale, geocoding in fase di scrittura, marker colorati, clustering su larga scala e filtraggio basato su array, il tutto poggiato su dati strutturati che mantengono gli annunci individuabili. Costruisci questi componenti su un'unica piattaforma geospaziale e le coordinate fluiscono in modo pulito dal geocoder alla mappa fino allo schema, senza chiamate duplicate e senza dati che divergono.
MapAtlas ti fornisce geocoding, reverse geocoding, ricerca di luoghi e rendering delle mappe per costruire tutto questo su un'infrastruttura ospitata nell'UE e conforme al GDPR. Esplora la Geocoding API e la Search API per iniziare a mappare la tua città.
Domande frequenti
Quali dati mi servono per creare una mappa degli eventi cittadini?
Come minimo, ogni evento ha bisogno dell'indirizzo di un locale, di una categoria e di un orario di inizio. L'indirizzo è ciò che trasforma un evento in un pin sulla mappa: lo geocodifichi una volta per ottenere latitudine e longitudine, memorizzi quelle coordinate e le riutilizzi ogni volta che mostri l'evento. Tutto il resto, come i link ai biglietti, le immagini e le descrizioni, sono metadati che alleghi al popup del marker.
Come trasformo l'indirizzo di un locale in coordinate sulla mappa?
Chiama un'API di geocoding con la stringa dell'indirizzo del locale e leggi latitudine e longitudine dalla risposta. Con la Geocoding API di MapAtlas invii l'indirizzo come query testuale a https://api.mapatlas.eu/geocoding/v1/search e usi le coordinate del primo risultato. Geocodifica ogni locale una sola volta quando l'evento viene creato, non a ogni caricamento della pagina, così la mappa resta veloce e il consumo di API rimane basso.
Quanti marker di eventi può mostrare una mappa prima di rallentare?
Il rendering dei singoli marker resta fluido fino a circa 100 o 200 pin in una vista con zoom ridotto. Oltre questa soglia, passa al clustering con una sorgente GeoJSON, che raggruppa gli eventi vicini in una singola bolla con un contatore a basso zoom e li separa man mano che l'utente ingrandisce. Un feed di eventi di tutta la città con centinaia di annunci dovrebbe usare il clustering fin dall'inizio.
Come permetto agli utenti di filtrare gli eventi per categoria o quartiere?
Tieni l'elenco completo degli eventi in memoria come array, associa una categoria e un quartiere a ciascun elemento e filtra quell'array in base alla selezione dell'utente. Poi aggiorna la sorgente della mappa con l'insieme filtrato invece di distruggere e ricostruire i marker. Sfogliare per quartiere funziona allo stesso modo: filtra gli eventi le cui coordinate ricadono nell'area selezionata, o che condividono lo stesso nome amministrativo ottenuto dal reverse geocoding.
Perché una mappa degli eventi ha bisogno di dati strutturati?
Una mappa visiva aiuta le persone, ma i motori di ricerca e gli assistenti IA leggono dati strutturati. Marcare ogni evento con i campi Event di schema.org, inclusi il nome del locale, le coordinate e l'orario di inizio, è ciò che permette a un annuncio di comparire nelle risposte a domande come 'cosa c'è stasera a Shoreditch'. Le stesse coordinate che posizioni sulla mappa alimentano i dati strutturati, così scoperta e visualizzazione provengono da un'unica fonte di verità.

