---
title: "Add interaction to landmarks | JavaScript maps SDK"
description: "Create a map with custom landmarks and add interactions like popups to display additional information."
---

> For AI agents: a documentation index is available at [/llms.txt](https://docs.maptiler.com/llms.txt). Markdown versions of all pages are available by appending .md to any URL.

# Add interaction to landmarks

In this tutorial, you’ll learn how to create a map with custom landmarks and add interactions to it.

Click on a landmark to open a popup with the landmark information

1.  Check out the step-by-step guide on [Creating a Custom Dataset (GeoJSON)](https://docs.maptiler.com/guides/vector-data-editor/) to create your desired landmarks.
2.  Follow the tutorial [How to Add Custom Landmarks to Your Map](https://docs.maptiler.com/guides/map-design/icons/), to create a map with the desired landmarks.
3.  We already have our map designed, now we are going to use it to create an interactive web map with our landmarks and get their information when you click on them. Just copy the below code:

### NPM module setup

```bash
npm install --save @maptiler/sdk
```

#### main.js

```js
import { Map, config } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';

config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE'; // Replace with your MapTiler API key.

const map = new Map({
  container: 'map',
  style: 'YOUR_CUSTOM_MAP_ID', // Replace with the style ID of your map created in step 2.
  center: [12.5, 41.9], // Update with the center coordinates of your map.
  zoom: 14
});

map.on('load', function () {
  const layerName = 'NAME_OF_YOUR_LANDMARKS_LAYER' // Replace with the name of the layer containing your landmarks.

  // When a click event occurs on a feature in the places layer, open a popup at the
  // location of the feature, with description HTML from its properties.
  map.on('click', layerName, function (e) {
    const coordinates = e.features[0].geometry.coordinates.slice();
    const description = e.features[0].properties.description;

    // Ensure that if the map is zoomed out such that multiple
    // copies of the feature are visible, the popup appears
    // over the copy being pointed to.
    while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
      coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
    }

    // Update the popup content to display properties of the feature created in step 1.
    const content = `
      <h3>${e.features[0].properties.title}</h3>
      <p>${description.slice(0, 300)}...</p>
      <a href="${e.features[0].properties.link}" target="_blank">More info</a>
    `;

    // Adjust the offset as needed based on the styling of the landmark layer.
    new maptilersdk.Popup({ offset: 40 })
      .setLngLat(coordinates)
      .setHTML(content)
      .addTo(map);
  });

  // Change the cursor to a pointer when the mouse is over the places layer.
  map.on('mouseenter', layerName, function () {
    map.getCanvas().style.cursor = 'pointer';
  });

  // Change it back to a pointer when it leaves.
  map.on('mouseleave', layerName, function () {
    map.getCanvas().style.cursor = '';
  });
});
```

#### index.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="robots" content="noindex">
  <title>Add interaction to landmarks | NPM example</title>
  <link rel="stylesheet" href="./style.css">
</head>
<body>
  <div id="map"></div>
  <script type="module" src="./main.js"></script>
</body>
</html>
```

#### style.css

```css
body {
  margin: 0;
  padding: 0;
}

#map {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
}

.maplibregl-popup {
  max-width: 400px;
  font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
}
```

### Basic JavaScript setup

```html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Landmark interactions</title>
  <script src="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.umd.min.js"></script>
  <link href="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.css" rel="stylesheet" />
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    #map {
      position: absolute;
      top: 0;
      bottom: 0;
      width: 100%;
    }

    .maplibregl-popup {
      max-width: 400px;
      font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
    }
  </style>
</head>

<body>
  <div id="map"></div>
  <script>
    maptilersdk.config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE'; // Replace with your MapTiler API key.

    const map = new maptilersdk.Map({
      container: 'map',
      style: 'YOUR_CUSTOM_MAP_ID', // Replace with the style ID of your map created in step 2.
      center: [12.5, 41.9], // Update with the center coordinates of your map.
      zoom: 14
    });

    map.on('load', function () {
      const layerName = 'NAME_OF_YOUR_LANDMARKS_LAYER' // Replace with the name of the layer containing your landmarks.

      // When a click event occurs on a feature in the places layer, open a popup at the
      // location of the feature, with description HTML from its properties.
      map.on('click', layerName, function (e) {
        const coordinates = e.features[0].geometry.coordinates.slice();
        const description = e.features[0].properties.description;

        // Ensure that if the map is zoomed out such that multiple
        // copies of the feature are visible, the popup appears
        // over the copy being pointed to.
        while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
          coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
        }

        // Update the popup content to display properties of the feature created in step 1.
        const content = `
          <h3>${e.features[0].properties.title}</h3>
          <p>${description.slice(0, 300)}...</p>
          <a href="${e.features[0].properties.link}" target="_blank">More info</a>
        `;

        // Adjust the offset as needed based on the styling of the landmark layer.
        new maptilersdk.Popup({ offset: 40 })
          .setLngLat(coordinates)
          .setHTML(content)
          .addTo(map);
      });

      // Change the cursor to a pointer when the mouse is over the places layer.
      map.on('mouseenter', layerName, function () {
        map.getCanvas().style.cursor = 'pointer';
      });

      // Change it back to a pointer when it leaves.
      map.on('mouseleave', layerName, function () {
        map.getCanvas().style.cursor = '';
      });
    });
  </script>
</body>

</html>
```

## Learn more

[Creating a custom vector dataset (GeoJSON)](https://docs.maptiler.com/guides/vector-data-editor/)

[How to Add Custom Landmarks to Your Map](https://docs.maptiler.com/guides/map-design/icons/)

## Related examples

### [Display a popup](https://docs.maptiler.com/sdk-js/examples/popup/)

Examples

Add an information popup to the map.

### [Attach a popup to a marker instance](https://docs.maptiler.com/sdk-js/examples/set-popup/)

Examples

Attach and display a popup to a map marker.

### [Display a popup on hover](https://docs.maptiler.com/sdk-js/examples/popup-on-hover/)

Examples

Show a popup when hovering over a custom marker.

### [Show polygon information on click](https://docs.maptiler.com/sdk-js/examples/polygon-popup-on-click/)

Examples

Display a popup when a user clicks a polygon.
