De meeste local discovery-producten staan of vallen bij één scherm: de kaart. Een gebruiker opent je app om een simpele vraag te beantwoorden, wat is er nu bij mij in de buurt, en de kaart is hoe hij dat beantwoordt. Die kaart goed krijgen, met de juiste pins, snel filteren en listings die zoekmachines echt kunnen lezen, is het kern-engineeringwerk achter elke evenementengids.
Deze gids loopt door het bouwen van een stadse evenementenkaart vanaf de grond: het modelleren van evenementdata, locaties geocoderen naar coördinaten, markers plotten en clusteren, filteren op categorie en buurt, en de listings vindbaar maken. Het gaat ervan uit dat je al weet hoe je een basiskaart rendert. Zo niet, begin dan met onze tutorial over hoe je interactieve kaarten aan je website toevoegt en kom hier terug voor de evenement-specifieke onderdelen.
Modelleer het Evenement rond zijn Locatie
Een evenement is iets tijdgebondens dat op een plek gebeurt. De plek is wat op de kaart komt, dus de locatie is het anker van je datamodel. Een minimaal evenementrecord ziet er zo uit:
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, // eenmalig gevuld door geocoding
neighbourhood: null, // eenmalig gevuld door reverse geocoding
startsAt: '2026-07-09T20:30:00Z',
url: 'https://example.com/tickets/8471',
};
De twee null-velden zijn belangrijk. Je wilt een locatie niet elke keer geocoderen als de kaart laadt. Geocodeer één keer, wanneer het evenement wordt aangemaakt of geïmporteerd, sla dan de coördinaten op en behandel ze als permanent.
Stap 1: Geocodeer elke Locatie naar Coördinaten
Geocoding zet een menselijk adres om in een breedte- en lengtegraad die je kunt plotten. Stuur de locatietekst naar de Geocoding API en lees de coördinaten uit het bovenste resultaat:
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 };
}
Draai dit op write time, wanneer een evenement je systeem binnenkomt, en persisteer de teruggegeven coördinaten op het record. Voor een volledige uitleg waarom de exacte pin-locatie ertoe doet, en hoe rooftop-coördinaten verschillen van de deur waar mensen daadwerkelijk naar binnen lopen, zie geocoding van gebouwingangen.
Stap 2: Plot Evenementen als Markers
Met coördinaten op elk evenement is plotten een loop. Geef elke categorie zijn eigen kleur zodat de kaart in één oogopslag leesbaar is:
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}">Tickets</a>`,
);
new mapmetricsgl.Marker({ color: CATEGORY_COLORS[evt.category] || '#0c3456' })
.setLngLat([evt.coords.lon, evt.coords.lat])
.setPopup(popup)
.addTo(map);
});
}
Dit is het patroon achter echte producten. Een live voorbeeld is OnlyHere, een dagelijkse gids voor dingen om te doen in Londen die elke locatie geocodeert en de evenementen van de dag op een interactieve MapAtlas-kaart plot, zodat een gebruiker kan bladeren door wat er te doen is per locatie en buurt in plaats van door een platte lijst te scrollen.
Stap 3: Cluster wanneer de Stad Volloopt
Losse markers zijn prima voor een handjevol evenementen. Een stadsbrede feed is geen handjevol. Zodra je voorbij ruwweg 100 tot 200 pins gaat, verplaats je de evenementen naar een GeoJSON source en laat je de kaart ze clusteren:
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 },
})),
},
});
Nu toont een drukke avond in het centrum één bubbel met een telling in plaats van honderd overlappende pins, en het cluster valt uit elkaar zodra de gebruiker inzoomt.
Stap 4: Filter op Categorie en Buurt
Filteren is waar een evenementenkaart een evenementenproduct wordt. Houd de volledige lijst in het geheugen en filter de array, geef daarna de gefilterde set aan de kaartbron in plaats van markers met de hand opnieuw te bouwen:
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;
}
Om het neighbourhood-veld te vullen, reverse-geocodeer je de coördinaten van elke locatie één keer en sla je de naam van het admin-gebied op. Die ene waarde voedt een buurt-dropdown, een "wat is er te doen in dit gebied"-weergave en een schonere listing-pagina, allemaal zonder een nieuwe lookup tijdens runtime.
Stap 5: Maak de Listings Vindbaar
Een kaart beantwoordt de vraag voor de persoon die al in je app zit. Voor het veel grotere publiek dat aan een zoekmachine of AI-assistent vraagt "wat is er vanavond te doen in Shoreditch" doet hij niets. Die systemen lezen gestructureerde data, geen pixels.
Markeer elk evenement met schema.org Event-velden en hergebruik de coördinaten die je al hebt:
{
"@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 }
}
}
De coördinaten die de pin tekenen, voeden ook de gestructureerde data, dus weergave en ontdekking komen uit één bron van waarheid. Dat is het verschil tussen een kaart die er goed uitziet en een product dat gevonden wordt. Voor meer over waarom machineleesbare locatiedata de zichtbaarheid in AI-zoekopdrachten aandrijven, zie onze gids over locatiespecifieke FAQ's voor AI-zoekopdrachten.
Alles bij Elkaar Brengen
Een stadse evenementenkaart bestaat uit vijf bewegende delen: een op de locatie verankerd datamodel, geocoding op write time, gekleurde markers, clustering op schaal en array-gebaseerd filteren, allemaal bovenop gestructureerde data die de listings vindbaar houdt. Bouw die delen op één geospatiaal platform en de coördinaten stromen schoon van de geocoder naar de kaart naar de schema, zonder dubbele lookups en zonder afwijkende data.
MapAtlas geeft je de geocoding, reverse geocoding, place search en kaartrendering om dit allemaal te bouwen op EU-gehoste, GDPR-conforme infrastructuur. Verken de Geocoding API en de Search API om je eigen stad te gaan plotten.
Veelgestelde vragen
Welke data heb ik nodig om een evenementenkaart voor een stad te bouwen?
Elk evenement heeft minimaal een adres van de locatie, een categorie en een starttijd nodig. Het adres maakt van een evenement een pin op de kaart: je geocodeert het één keer om breedte- en lengtegraad te krijgen, slaat die coördinaten op en hergebruikt ze telkens als het evenement wordt getoond. Al het andere, zoals ticketlinks, afbeeldingen en beschrijvingen, is metadata die je aan de popup van de marker hangt.
Hoe zet ik een locatieadres om in kaartcoördinaten?
Roep een geocoding-API aan met de adrestekst van de locatie en lees de breedte- en lengtegraad uit de response. Met de MapAtlas Geocoding API stuur je het adres als tekstquery naar https://api.mapatlas.eu/geocoding/v1/search en gebruik je de coördinaten van het bovenste resultaat. Geocodeer elke locatie één keer, wanneer het evenement wordt aangemaakt, niet bij elke page load, zodat de kaart snel blijft en je API-gebruik laag.
Hoeveel evenement-markers kan een kaart tonen voordat hij traag wordt?
Losse markers renderen blijft soepel tot ruwweg 100 tot 200 pins in een uitgezoomde weergave. Daarboven schakel je over op GeoJSON source clustering, dat nabije evenementen bij laag zoomniveau samenvoegt in één telbubbel en ze uit elkaar haalt zodra de gebruiker inzoomt. Een stadsbrede evenementenfeed met honderden listings gebruikt vanaf het begin clustering.
Hoe laat ik gebruikers evenementen filteren op categorie of buurt?
Houd de volledige evenementenlijst als array in het geheugen, hang aan elk item een categorie en een buurt, en filter die array op basis van de keuze van de gebruiker. Update daarna de kaartbron met de gefilterde set in plaats van markers te vernietigen en opnieuw op te bouwen. Bladeren per buurt werkt hetzelfde: filter op de evenementen waarvan de coördinaten binnen het geselecteerde gebied vallen, of die dezelfde admin-naam delen uit reverse geocoding.
Waarom heeft een evenementenkaart gestructureerde data nodig?
Een visuele kaart helpt mensen, maar zoekmachines en AI-assistenten lezen gestructureerde data. Elk evenement markeren met schema.org Event-velden, inclusief de naam van de locatie, coördinaten en starttijd, is wat een listing laat opduiken in antwoorden op vragen als 'wat is er vanavond te doen in Shoreditch'. Dezelfde coördinaten die je op de kaart plot, voeden de gestructureerde data, zodat ontdekking en weergave uit één bron van waarheid komen.

