# API Reference for Map Widget

{% hint style="warning" %}
You are reading the **Classic Widget Documentation**

Classic widgets are a previous widget version for onsite widgets created before September 23rd.

From September 23rd 2025, all new widgets created will be NextGen.

Please check your widget version on the **Widget List page** to see if it is **Classic** or **NextGen** widget.

You can read the [Nextgen widget documentation here](https://docs.nosto.com/ugc/guides/widgets-nextgen).

**Note: This feature is unique to Classic widgets**
{% endhint %}

* [Background](#background)
  * [Geohash](#background-geohash)
  * [Execution flows](#background-execution-flows)
* [Methods](#methods)
  * [.initialize(options)](#method-initialize)
  * [.createMap()](#method-createMap)
  * [.createLayer(style)](#method-createLayer)
  * [.handleMarkerClick(event)](#method-handleMarkerClick)
  * [.handleMoveEnd()](#method-handleMoveEnd)
  * [.createMarkerBySummary(summary)](#method-createMarkerBySummary)
  * [.on(eventName, handler)](#method-on)
  * [.getAggregatedDataByBounds(sw, ne, numGeohashPerView)](#method-getAggregatedDataByBounds)
* [Exported methods](#exported-methods)
  * [.getAggregatedDataByBounds(sw, ne, numGeohashPerView)](#exported-method-getAggregatedDataByBounds)
* [Customization examples](#customization-examples)
  * [Add logic before/after the map widget starts](#customization-example-add-logic-before-after-map-widget-starts)
  * [Initialize Leaflet with custom options](#customization-example-initialize-leaflet-with-custom-options)
  * [Use a different map layer (e.g. Google Maps)](#customization-example-use-a-different-map-layer-eg-google-maps)

## Background

The Map plugin’s purpose is to provide a visualization of where content is happening.\
This adds value when the location of content is as important as the content itself.

* The Mapping Widget overlays geo-filtered content as Pins on a map;
* The user sets the initial viewing area
* The user can choose from various mapping providers – Google Maps, Mapzen, CartoDB and OpenStreetMap
* They can customize the appearance of the Map based on which provider they choose
* Each Pin reflects a Tile or a cluster (group) of Tiles
* The Pin size is relative to the cluster size. The bigger the Pin, the more content that it represents.
* The user can zoom in and out on the map to see a more refined location of the Pins

### Geohash

Tiles in the Maps Widget are grouped into clusters using Geohash. Geohash is a string representation of coordinates.

> Geohash is a geocoding system invented by Gustavo Niemeyer and placed into the public domain. It is a\
> hierarchical spatial data structure which subdivides space into buckets of grid shape, which is one of the many\
> applications of what is known as a Z-order curve, and generally space-filling curves.

Reference [Wikipedia: Geohash](https://en.wikipedia.org/wiki/Geohash)

### Execution flows

#### Map widget creation

1. MapWidget is created. `var widget = new MapWidget()`
2. Custom JS code is executed `// custom javascript`
3. The widget is initialized. `widget.initialize()`
   1. Leaflet map is created. `var map = widget.createMap()`
   2. Map layer is created. `map.setLayer(widget.createLayer())`

#### On map move

1. On move, the end is called. `widget.handleMoveEnd()`
   1. Get all tile summaries for the current visible area. `var summaries = widget.getAggregatedDataByBounds()`
   2. Render the fetched summaries. `widget.renderSummaries(summaries)`

#### On marker clicked

1. On marker, click is called. `widget.handleMarkerClick()`

## Methods

### .initialize(options)

Initialize the map widget.

**Parameters**

| Name    | Type       | Description |
| ------- | ---------- | ----------- |
| options | \`Object\` | Options     |

**Return**\
`Promise` A promise that resolves when initialization completes.

### .createMap()

Creates a Leaflet Map object.

**Return**\
`L.Map` The created map object.

### .createLayer(style)

Creates a Leaflet Map object.

**Parameters**

| Name  | Type       | Description  |
| ----- | ---------- | ------------ |
| style | \`Object\` | Style object |

**Return**\
`L.Layer` The created map object.

### .handleMarkerClick(event

Handles marker click. The default implementation is updates the content list if it is connected to a\
content widget. Otherwise, it only emits the ‘marker:click’ event which can be listen using [`.on`](#method-on)

**Parameters**

| Name  | Type      | Description |
| ----- | --------- | ----------- |
| event | \`Event\` | Click event |

**Return**\
`void`

#### Example usage

```
widget.handleMarkerClick = function (event) {
    var $dom = $(event.originalEvent.target);
    // do something

    // call parent method (optional)
    Widget.prototype.handleMarkerClick.call(widget, event);
};
```

### .handleMoveEnd()

Handles map panning, resizing and zooming.

**Return**\
`void`

### .createMarkerBySummary(summary)

Creates a Leaflet Map object.

**Parameters**

<table><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>summary</td><td><pre><code>{
</code></pre></td><td></td></tr></tbody></table>

```
geohash:String,––
quantity:Integer,
avg_location:{
    longitude:Float,
    latitude:Float
}
```

} | Summary object |

**Return** `L.Marker` The marker object.

### .on(eventName, handler)

Listens to an event.

**Parameters**

| Name      | Type                           | Description        |
| --------- | ------------------------------ | ------------------ |
| eventName | \`String\`                     | Event name         |
| handler   | \`Function(data:Object):void\` | A handler function |

**Return**\
`MapWidget` The current map widget object.

#### Example usage

```
// Event 'marker:click' might not emit if handleMoveEnd() or handleMarkerClick() is overrode.
widget.on('marker:click', function (summary) {
    console.log('Geohash: ' + summary.geohash);
    console.log('Quantity: ' + summary.quantity);
    console.log('Average longitude: ' + summary.avg_location.longitude);
    console.log('Average latitude: ' + summary.avg_location.latitude);
});
```

### .getAggregatedDataByBounds(sw, ne, numGeohashPerView)

Listens to an event.

**Parameters**

| Name              | Type                       | Description                                                                       |
| ----------------- | -------------------------- | --------------------------------------------------------------------------------- |
| sw                | \`{lat:Float, lng:Float}\` | South west coordinates                                                            |
| ne                | \`{lat:Float, lng:Float}\` | North east coordinates                                                            |
| numGeohashPerView | \`Integer\`                | (Optional) Max number of geohashes to generate in the given view. Default: \`32\` |

**Return**\
`Promise<Summary[]>` A promise that resolves to summaries.

## Exported methods

Exported methods can be called in parent window.

### .getAggregatedDataByBounds(sw, ne, numGeohashPerView)

See [.getAggregatedDataByBounds(sw, ne, numGeohashPerView)](#method-getAggregatedDataByBounds)

#### Example usage (own Google Maps)

```javascript
    var map; // Google Map instance
    // get the map widget by ID
    var mapWidget = Stackla.WidgetManager.getWidgetInstanceByWidgetId(1234);
    map.addListener('bounds_changed', function () {
        var bounds = map.getBounds();
        var sw = bounds.getSouthWest();
        var ne = bounds.getNorthEast();
        mapWidget.getAggregatedDataByBounds(
            {lat: sw.lat(), lng: sw.lng()},
            {lat: ne.lat(), lng: ne.lng()},
            16
        ).then(function (summaries) {
    
        }).catch(function (ex) {
            console.error(ex);
        });
    });
```

## Customization examples

### Add logic before/after map widget starts.

It is possible to add logic before and after the widget initializes. Below is an example using [Promise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise).

```javascript
widget.initialize = function (options) {
        (new Promise(function (resolve, reject) {
            try {
                // perform necessary options before widget initialization starts.
                // ...
                // ...

                // at the end, call resolve()
                resolve();
            } catch (ex) {
                reject(ex);
            }
        }).then(function () {
            return MapWidget.prototype.initialize.call(widget, options);
        }).then(function () {
            // then perform actions after widget initialization is completed.
        }).catch(function (ex) {
            // catch error/exception
            console.error(ex);
        });
    };
```

### Initialize Leaflet with custom options

```javascript
// Leaflet options @see http://leafletjs.com/reference-1.0.0.html#map-factory
    widget.createMap = function () {
        var map = L.map('map', {
            maxBounds: [
                [-85.0, -180.0],
                [85.0, 180.0]
            ],
            scrollWheelZoom: false
        });
        return map;
    };
```

### Use a different map layer (e.g. Google Maps)

```javascript
// You can create your own Google Map style here https://mapstyle.withgoogle.com/
    widget.createLayer = function (style) {
        return L.gridLayer.googleMutant({
            styles: styles,
            type: 'roadmap'
        });
    };
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.nosto.com/ugc/api-docs/javascript/widgets/map-widget.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
