This add-on adds a Map facet type, which works just like any other facet type. The generated map displays geocoded results and can also filter results by showing only results within the map viewport.

Combine a Map facet with a Proximity facet

A Map facet can be combined well with a Proximity facet, which returns results within a chosen radius from a specified location.

When a location and radius are set (or changed) with the Proximity facet, the map will automatically zoom in or out, showing the locations that are within the radius of the set location. It will also display a marker pin at the set location (which can be customized or disabled).

Available options

Name Description
Data source The Data source should be a custom field containing a comma-separated latitude, longitude, or a latitude only, if you use a separate custom field for the longitude.
Longitude Choose a custom field to use for the longitude value, if stored separately from the latitude (optional). See below for more info.
Map design Choose a design / style / color scheme for the map. To use a custom style, see below
Marker clustering This option will group markers into marker clusters from a certain zoom level (see below)
Ajax marker content Enable to dynamically load marker content via AJAX. Works best for maps with many markers, since it prevents all the marker content from loading all at once
Marker limit
  • Show all results – will show all markers that match the results
  • Show current page results – will only display markers matching the results on the current page of paginated results
Map width / height Width and height of map. Use unitless for px, e.g. 300, or with %, e.g. 100%
Zoom min / max Set the minimum and maximum zoom level. The values must be a number between 1 (minimum zoom) and 20 (maximum zoom)
Fallback lat / lng / zoom: Set a fallback location (lat/lng) and/or zoom level. The zoom level must be a number between 1 (minimum zoom) and 20 (maximum zoom). These settings are only used when no results/markers are found. To set a custom center and/or zoom level, see below
Marker content Enter display code (HTML and/or PHP) to create the content that displays in an info window popup when a marker is selected. For an example, see below

Data source

The Data source should be a custom field containing a comma-separated latitude, longitude.

You can also use separate custom fields for the latitude and longitude, see the available options.

Other data sources

The following plugins and themes offer dedicated custom fields for latitude and longitude that can be used as data sources for the Map facet. Click the links for specific instructions on using these fields:

Google Maps API key

Generate a Google Maps API key

The Map facet requires a valid Google Maps API key. To generate a key, you have to log into Google Cloud Console, set up a project, add an API key under API's & Services > Credentials, and enable the following three API services for the key:

  1. Maps JavaScript API: required for the Map / Proximity facets to work
  2. Geocoding API: required for the Proximity facet’s “Locate me” button
  3. Places API: required for the Proximity facet’s autocomplete box

To be able to use the key, you also need to set up a Billing Account in Google Cloud Console, and add your project to it. You will need a creditcard to set up billing. There is a free monthly credit of $200, which amounts to 28000+ map loads per month.

Add the Google Maps API key to FacetWP

After generating an API key, add it to: Settings > FacetWP > Settings > Google Maps API key.
Both the Map facet and the Proximity facet use this key.

Besides in FacetWP’s settings, the API key can also be set with a constant in wp-config.php:

define( 'GMAPS_API_KEY', 'your-api-key' ); 

Or with a hook in your (child) theme’s functions.php:

add_filter( 'facetwp_gmaps_api_key', function( $api_key) {
    return 'your-api-key';
});

Add the Google Maps API key to Advanced Custom Fields

If you are using the Advanced Custom Fields Google Map field as the data source, make sure you pass the same Google Maps API key into ACF. ACF needs the Google Maps API in the backend to geolocate the address entered for each post.

Add the Google Maps API key to Listify, Listable, WP Job Manager

If you are using Listify theme, Listable theme and/or the WP Job Manager plugin, make sure to also add the Google Maps API key to:
(Job) Listings > Settings > Google Maps API Key

The Listify theme itself has a second settings to enter the Google Maps API key, at:
Appearance > Customize > Listings > Map settings

Localize your map or add URL parameters

When FacetWP loads a Google map, the script loading URL contains several specific URL parameters that determine which Google Map libraries are loaded and what your Google Maps API key is. The URL looks like this:

https://maps.googleapis.com/maps/api/js?libraries=places&key=YOUR_API_KEY

As is standard in URLs, all parameters must be separated using the ampersand (&) character.

Using the facetwp_gmaps_url filter, you can filter the URL and pass additional URL parameters to the Google Maps API. See below for an example:

Localize your map

By default, the Google Maps API will attempt to automatically load the most appropriate language and region based on the user’s location or browser settings. However, if you want to explicitly set a fixed region and/or language for the map, you can use the region and language parameters.

The region parameter allows you to localize the behavior and features of the map, based on the country or region set. The language parameter parameters lets you translate the map’s user interface.

The following example sets the map’s region to The Netherlands, and the language to Dutch:

add_filter( 'facetwp_gmaps_url', function( $url) {
  $url = $url . '&region=NL&language=nl';
  return $url;
} );

Add marker content

The “Marker content” setting can be used to create the content of the info window popup that displays when a marker is selected. The setting’s field accepts HTML and PHP code.

The following example outputs the title, link, and excerpt:

<h3>
  <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
    <?php the_title(); ?>
  </a>
</h3>
<?php the_excerpt(); ?>

The “Enable map filtering” button

The purpose of map filtering is to refresh the results whenever the map is zoomed or panned.
So after clicking the button, then zooming or panning the map, only results within the map’s viewport are shown in the filtered listing. You can see this in action in the State Parks map demo.

Disable the “Enable map filtering” button

Currently, there is no setting to disable the ‘Enable map filtering’ button/functionality. If you don’t want this button to show, you can hide the button with CSS:

.facetwp-map-filtering { 
    display: none; 
}

Change the “Enable map filtering” button text

The text of the “Enable map filtering” button can be changed with this code:

add_filter( 'gettext', function ( $translated_text, $untranslated_text, $domain ) {
    if ( $translated_text == 'Enable map filtering' && 'facetwp-map-facet' == $domain ) {
        $translated_text = 'Your button text';
    }
    return $translated_text;
}, 10, 3 );

Enable map filtering on load of the map

You can enable map filtering by default on load of the map with this code:

<?php
    add_action( 'wp_footer', function () {
    ?>
    <script>
        (function ($) {
            $(document).on('facetwp-loaded', function () {
                if ('undefined' === typeof FWP_MAP) {
                    return;
                }
                var filterButton = $(".facetwp-map-filtering");
                if (!filterButton.hasClass('enabled') && 'undefined' == typeof FWP_MAP.enableFiltering) {
                    filterButton.text(FWP_JSON['map']['resetText']);
                    FWP_MAP.is_filtering = true;
                    filterButton.addClass('enabled');
                    FWP_MAP.enableFiltering = true;
                }
            });
        })(jQuery);
    </script>
    <?php
}, 100 );

Common issues with “Enable map filtering”

If the “Enable map filtering” button is not working, make sure you have not disabled auto_refresh. That also disabled the map from auto-refreshing.

Change the map type

Google maps can be displayed in four different basic map types:

  • roadmap displays the default road map view.
  • satellite displays Google Earth satellite images.
  • hybrid displays a mixture of normal and satellite views.
  • terrain displays a physical map based on terrain information.

The default map type is roadmap, which the user can change to the other map types with a Map Type Control (see below) in the left top corner of the map. You can set any of the four map types as default. The following code sets the map type to terrain:

add_filter( 'facetwp_map_init_args', function ( $args ) {
    $args['init']['mapTypeId'] = 'terrain'; // valid options are: roadmap, satellite, hybrid, terrain
    return $args;
});

Turn off the map controls

Google maps display several UI elements to allow user interaction with the map. These elements are known as “controls”.

The default controls can be individually, or all removed with the following code:

add_filter( 'facetwp_map_init_args', function ( $args ) {

  $args['init']['zoomControl']       = false; // +- zoom control
  $args['init']['mapTypeControl']    = false; // roadmap / satellite toggle
  $args['init']['streetViewControl'] = false; // street view / yellow man icon
  $args['init']['fullscreenControl'] = false; // full screen icon

  /** this overwrites all 4 lines above and will disable ALL of the default ui icons instead of the individual icons above */
  $args['init']['disableDefaultUI']  = true; // disable the default ui

  return $args;

} );

Reposition the map controls

Besides turning them off, you can also reposition the map controls, with the code below.

You have to reposition each control separately. Use the control names from the previous code example, or check the controls documentation.

It does not work to pass the documented control positions directly to the Map facet. You have to pass the number of which it is an alias:

TOP_LEFT: 1,
TOP_CENTER: 2,
TOP: 2,
TOP_RIGHT: 3,
LEFT_CENTER: 4,
LEFT_TOP: 5,
LEFT: 5,
LEFT_BOTTOM: 6,
RIGHT_TOP: 7,
RIGHT: 7,
RIGHT_CENTER: 8,
RIGHT_BOTTOM: 9,
BOTTOM_LEFT: 10,
BOTTOM_CENTER: 11,
BOTTOM: 11,
BOTTOM_RIGHT: 12,
CENTER: 13

The following example moves the “Zoom Control” (the plus-minus buttons) to the left bottom position:

add_filter( 'facetwp_map_init_args', function ( $args ) {
  $args['init']['zoomControl']       = true;
  $args['init']['zoomControlOptions']['position'] = 6;  // 6 = LEFT_BOTTOM
  return $args;
} );

Use a custom map style / design

The Map facet type offers four alternative styles besides the default look, which you can choose with the “Map design” setting.

If these styles are not what you are looking for, it is possible to design your own map style or download a pre-made style from a map style library. With a custom map style, you can not only change the color scheme, but also how and if map features like roads, administrative areas or points of interest are displayed, or not:

A simple greyscale custom Google map style
Custom map style “Subtle Greyscale Map” from SnazzyMaps.

Two websites where you can build your own or download a pre-made custom map style are:

To use a custom map style:

  1. Build or choose the map style in one of the mentioned websites;
  2. Copy or download the resulting JSON array (which begins and ends with square brackets);
  3. Replace the JSON array in the code example below, between the single quotes, with your copied / downloaded JSON array;
  4. Add the code to your (child) theme’s function.php.
add_filter( 'facetwp_map_init_args', function( $args ) {
  $args['init']['styles'] = json_decode( '[{"featureType":"administrative","elementType":"labels.text.fill","stylers":[{"color":"#444444"}]},{"featureType":"landscape","elementType":"all","stylers":[{"color":"#f2f2f2"}]},{"featureType":"poi","elementType":"all","stylers":[{"visibility":"off"}]},{"featureType":"road","elementType":"all","stylers":[{"saturation":-100},{"lightness":45}]},{"featureType":"road.highway","elementType":"all","stylers":[{"visibility":"simplified"}]},{"featureType":"road.arterial","elementType":"labels.icon","stylers":[{"visibility":"off"}]},{"featureType":"transit","elementType":"all","stylers":[{"visibility":"off"}]},{"featureType":"water","elementType":"all","stylers":[{"color":"#46bcec"},{"visibility":"on"}]}]' );
  return $args;
} );

Set a custom zoom level or location/center

To determine the map center and correct zoom level, the map uses Google Maps’ fitBounds function. On every refresh, the map automatically pans to the center of all found markers, and zooms to the zoom level where all found markers fit within the bounds of the map. There is no easy way to change the zoom level that fitBounds ends up using after a page load or refresh.

The Map facet does have a setting called “Fallback lat / lng / zoom” where you can enter a custom center (lat/lng) and/or zoom level. These values are only used as a fallback, when no results/markers are found. In all other situations, these settings have no effect because the map uses the fitBounds function.

However, with a bit of custom code, this behaviour can be overwritten, so you can actually use the “Fallback lat / lng / zoom” setting to set a custom center and/or zoom level on initial page load, or on every facet refresh.

Add the following code to your (child) theme’s function.php and set a custom lat/lng and/or zoom level in the Map facet settings.

To force the custom lat/lng/zoom settings only on the initial page load:

<?php
  add_action( 'wp_head', function() {
  ?>
    <script>
      document.addEventListener('DOMContentLoaded', function() {
        if ('undefined' !== typeof FWP && 'undefined' !== typeof FWP.hooks) {
          FWP.hooks.addFilter('facetwp_map/fit_bounds', function(fit_bounds) {
            return FWP.loaded; // force the custom lat/lng/zoom only on initial page load
          });
        }
      });
    </script>
  <?php
}, 100 );

To force the custom lat/lng/zoom settings on initial page load and every facet refresh:

<?php
  add_action( 'wp_head', function() {
  ?>
    <script>
      document.addEventListener('facetwp-refresh', function() {
        if ('undefined' !== typeof FWP && 'undefined' !== typeof FWP.hooks) {
          FWP.hooks.addFilter('facetwp_map/fit_bounds', function(fit_bounds) {
            return false; // force the custom lat/lng/zoom on every refresh
          });
        }
      });
    </script>
  <?php
}, 100 );

Customize the marker pins

You can change the marker pin images with the following code. Make sure to use a transparent PNG or SVG.

add_filter( 'facetwp_map_marker_args', function( $args, $post_id ) {
    $args['icon'] = get_template_directory_uri() . '/assets/images/marker.png'; // set your theme image path here
    return $args;
}, 10, 2 );

For more flexibility, you could alternatively use arrays to mimic Google Map API’s JS objects:

add_filter( 'facetwp_map_marker_args', function( $args, $post_id ) {
    $args['icon'] = [
        'url' => get_template_directory_uri() . '/assets/images/marker.png', // set your theme image path here
        'scaledSize' => [
            'width' => 16,
            'height' => 16
        ]
    ];
    return $args;
}, 10, 2 );

Customize the marker pins for selected posts only

The following example is the same as the previous one, but changes the marker pins only for specific posts:

add_filter( 'facetwp_map_marker_args', function( $args, $post_id ) {
  $myposts_with_custom_markers = array(101, 102, 103); // array with the post id's of posts that need a custom marker
  if ( in_array( $post_id, $myposts_with_custom_markers ) ) {
    $args['icon'] = [
      'url'        => get_template_directory_uri() . '/assets/images/marker.png', // set your theme image path here
      'scaledSize' => [
        'width'  => 16,
        'height' => 16
      ]
    ];
  }
  return $args;
}, 10, 2 );

Customize the marker pins for each post category or term

You could select posts based on any post property available through the $post_id parameter. An example would be to give each post category/term a different marker pin, using has_category() or has_term():

add_filter( 'facetwp_map_marker_args', function( $args, $post_id ) {
  if (has_term( 'my-term-slug', 'my-taxonomy', $post_id)) { // replace with your term slug and taxonomy
    $args['icon'] = [
      'url'        => get_template_directory_uri() . '/assets/images/marker.png', // set your theme image path here
      'scaledSize' => [
        'width'  => 16,
        'height' => 16
      ]
    ];
  }
  return $args;
}, 10, 2 );

Customize the Proximity facet marker pin

The default Proximity facet marker pinIf you are using the map with a Proximity facet, when a location is entered, a yellow location marker is displayed on the map.

With the following code, you can change the proximity marker pin’s path, color, opacity, scale, and anchor. The code example shows the default icon settings. All of these settings need to have a value.

add_filter( 'facetwp_map_proximity_marker_args', function( $args ) {
  $args['icon'] = [
    'path'        => 'M8,0C3.582,0,0,3.582,0,8s8,24,8,24s8-19.582,8-24S12.418,0,8,0z M8,12c-2.209,0-4-1.791-4-4 s1.791-4,4-4s4,1.791,4,4S10.209,12,8,12z',
    'fillColor'   => 'gold',
    'fillOpacity' => 0.8,
    'scale'       => 0.8,
    'anchor'      => [ 'x' => 8.5, 'y' => 32 ]
  ];
  return $args;
}, 10 );

You can also replace the default proximity marker pin with a custom marker image, with the following code. Make sure to use a transparent PNG or SVG.

add_filter( 'facetwp_map_proximity_marker_args', function( $args ) {
  $args['icon'] = get_template_directory_uri() . '/assets/images/marker.png'; // set your theme image path here
  return $args;
}, 10 );

For more flexibility, you could alternatively use arrays to mimic Google Map API’s JS objects:

add_filter( 'facetwp_map_proximity_marker_args', function( $args ) {
  $args['icon'] = [
    'url'        => get_template_directory_uri() . '/assets/images/marker.png', // set your theme image path here
    'scaledSize' => [
      'width'  => 16,
      'height' => 16
    ]
  ];
  return $args;
}, 10 );

Disable the Proximity facet marker pin

If you want to completely disable the proximity marker pin, you can use this hook:

add_filter( 'facetwp_map_proximity_marker_args', '__return_false' );

Marker clustering

If you have large numbers of markers in one area, you can enable the “marker clustering” option. Marker clustering combines markers of close proximity into clusters, simplifying the display of markers on the map.

The marker clusterer library used by FacetWP, and its options, methods and examples can be found here.

Set marker cluster to zoom in when clicking on it

The behaviour of the map after clicking on a marker cluster can be set to zoom into it with this code:

add_filter( 'facetwp_map_init_args', function( $args ) {
  if ( isset( $args['config']['cluster'] ) ) {
    $args['config']['cluster']['zoomOnClick'] = true; // default: false
  }
  return $args;
} );

Set the maximum zoom level for a cluster to appear

The maximum zoom level that a marker can be part of a cluster can be set like this:

add_filter( 'facetwp_map_init_args', function( $args ) {
  if ( isset( $args['config']['cluster'] ) ) {
    $args['config']['cluster']['maxZoom'] = 10; // default: 15. Level must be between 1 and 20.
  }
  return $args;
} );

Set the minimum number of markers in a cluster

The minimum number of markers to be in a cluster before the markers are hidden and a count is shown can be set like this:

add_filter( 'facetwp_map_init_args', function( $args ) {
  if ( isset( $args['config']['cluster'] ) ) {
    $args['config']['cluster']['minimumClusterSize'] = 5; // default: 2
  }
  return $args;
} );

Customize the marker cluster images

Default marker cluster image icons example
The default five PNG marker cluster icons

The marker clusterer library used by FacetWP comes with five PNG cluster icon images, in ascending specific sizes.

The cluster icons’ sizes and colors represent the number of markers in the cluster. Which of the five cluster icons is shown, is calculated based on the total number of markers and the percentage of markers in that specific cluster.

With the two methods described below, it is possible to change the default cluster images and their sizes.

Using the second method, you can also change the icon number’s text size and text color (which is black by default).

Method 1: Using imagePath and imageExtension

To simply replace the five default marker cluster icons with your own icons, use the following code:

add_filter( 'facetwp_map_init_args', function( $args ) {
  if ( isset( $args['config']['cluster'] ) ) {
    $args['config']['cluster']['imagePath']      = get_template_directory_uri() . '/assets/img/googlemaps/m'; // set your own image directory in your theme here. Note: the /m at the end is not a directory, but the first part of the image names.
    $args['config']['cluster']['imageExtension'] = 'png'; // 'svg' will work too
  }
  return $args;
} );

For this to work, you need to make a custom directory in your theme. In the above example, this directory would be /assets/img/googlemaps. The /m in the specified directory is the first part of the image name.

In this example, the five images need the following specific names and sizes to work:

m1.png (size: 53x53 px, default color: blue)
m2.png (size: 56x56 px, default color: yellow)
m3.png (size: 66x66 px, default color: red)
m4.png (size: 78x78 px, default color: magenta)
m5.png (size: 90x90 px, default color: purple)

Note: You can use SVGs instead of PNGs. Just change imageExtension to 'svg'.

Method 2: Using the styles array

If you need more control, instead of using the imagePath and imageExtension options, you can use the styles array. With this method you can not only set custom cluster images and sizes, but also change the cluster icons’ text color and text sizes.

The following example uses the default icon directory and icon sizes. It sets the cluster icon text (the number of markers in the cluster) to a size of 16px, and the color to #ffffff (white).

If you want to use custom icons and sizes, you can specify a directory in your theme with the 'url' option, and place five images in it (see the previous example). Note that the /m in the specified directory is not a directory but the first part of the image name. You can specify five custom icon sizes in the $clustericonsizes array.

The two-dimensional styles array needs five child arrays, for each of the five marker cluster icons, in ascending sizes:

add_filter( 'facetwp_map_init_args', function( $settings ) {
  $clustericonsizes = array( 53, 56, 66, 78, 90 );  // specify icon image sizes. These are the default values.
  for ( $i = 1; $i <= 5; $i ++ ) {
    $settings['config']['cluster']['styles'][] = [
      'url'       => FACETWP_MAP_URL . '/assets/img/m' . $i . '.png', // directory, required. This is the default directory. The url becomes the CSS background-image url.
      'width'     => $clustericonsizes[ $i - 1 ], // required
      'height'    => $clustericonsizes[ $i - 1 ], // required
      'textColor' => '#ffffff', // white, optional
      'textSize'  => 16 // 16px, optional
  //  'anchor' => [10,20], // Optional. Anchor position of the label text. By default label text is centered horizontally and vertically in the icon. [10,20] means 10px from the top of the icon (y) and 20px (x) from the left of the icon. Values need to be smaller than width and height of the icon to take effect.
  //  'iconAnchor' => [10,20], // Optional. The negative anchor position of the icon. [10,20] means the left top of the icon is 10px left of the lat/lng center, and 20px above the lat/lng center. Without iconAnchor values, the icon is centered on the lat/lng center horizontally and vertically.
  //  'backgroundPosition' => '5px 10px' // Optional. The CSS background-position of the icon images, including 'px'. Default= '0,0'.
    ];
  }
  return $settings;
} );

The following example shows how to use one SVG image for all five cluster image sizes. It also sets five custom ascending image sizes and text sizes, and sets the text color to white:

add_filter( 'facetwp_map_init_args', function( $settings ) {
  $clustericonsizes     = array( 40, 45, 50, 55, 60 ); // specify custom icon image sizes
  $clustericontextsizes = array( 12, 14, 16, 18, 20 ); // specify custom icon text sizes
  for ( $i = 1; $i <= 5; $i ++ ) {
    $settings['config']['cluster']['styles'][] = [
      'url'       => 'https://yourdomain/wp-content/themes/yourtheme/yourimages/clustericon.svg', // custom directory, required. The url becomes the CSS background-image url.
      'width'     => $clustericonsizes[ $i - 1 ], // required
      'height'    => $clustericonsizes[ $i - 1 ], // required
      'textColor' => '#ffffff', // white, optional
      'textSize'  => $clustericontextsizes[ $i - 1 ], // optional
  //  'anchor' => [10,20], // Optional. Anchor position of the label text. By default label text is centered horizontally and vertically in the icon. [10,20] means 10px from the top of the icon (y) and 20px (x) from the left of the icon. Values need to be smaller than width and height of the icon to take effect.
  //  'iconAnchor' => [10,20], // Optional. The negative anchor position of the icon. [10,20] means the left top of the icon is 10px left of the lat/lng center, and 20px above the lat/lng center. Without iconAnchor values, the icon is centered on the lat/lng center horizontally and vertically.
  //  'backgroundPosition' => '5px 10px' // Optional. The CSS background-position of the icon images, including 'px'. Default= '0,0'.
    ];
  }
  return $settings;
} );

Method 3: Using cssClass

The third way of customizing cluster icons is by using the cssClass option of the marker clusterer library. The cluster “icons” in the code will then consist of a div with the custom class you set, and will contain only the cluster icon text (the number of markers in the cluster):

add_filter( 'facetwp_map_init_args', function( $args ) {
  if ( isset( $args['config']['cluster'] ) ) {
    $args['config']['cluster']['cssClass'] = 'my-cluster-class'; 
  }
  return $args;
} );

You can then style the cluster icons in any way you like. Below is an example of accompanying CSS to style the .my-cluster-class div, resulting in a cluster icon looking like the image on the right.

Be aware that the position: absolute; rule is not optional.

.my-cluster-class {
    position: absolute; /* not optional */
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: #ff0000;
    border: 2px solid #fff;
    cursor: pointer;
    color: #fff;
    font-weight: bold;
    font-size: 14px;
    line-height: 32px;
    text-align: center;
}

Marker clustering and the Proximity marker pin

If you are using the map with a Proximity facet, a yellow location marker is displayed on the map when a location is entered. This marker will be part of the closest marker cluster and will also be counted in the cluster’s displayed number. If you don’t want this to happen, it is possible to disable the Proximity marker pin.

Customize cluster click behavior

If you want to customize the functionality of the map clusters, the following code shows how to access the marker cluster click event.

Two basic examples are shown: the first uses fitBounds() to zoom into a cluster when it is clicked, which essentially does the same as setting zoomOnClick to true. The second example gets all markers in the clicked cluster, with the getMarkers() method.

More methods that can be used with the marker clusterer library can be found here.

<?php
  add_action( 'wp_footer', function() {
  ?>
    <script type="text/javascript">
      (function($) {

        ClusterIcon.prototype.triggerClusterClick = function() {

          var markerClusterer = this.cluster_.getMarkerClusterer();

          // Trigger the clusterclick event
          google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_);

          // Your code here. Two examples:

          // Example 1: Zoom in to bounds of cluster. Does the same as when zoomOnClick is set to true
          this.map_.fitBounds(this.cluster_.getBounds());

          // Example 2: Put all markers in the clicked cluster into an object
          var markers = this.cluster_.getMarkers();
          console.log(markers);

        }
      })(jQuery);
    </script>
  <?php
}, 100 );

Overlapping Marker Spiderfier

Map facet Overlapping Marker SpiderfierThe Map facet has a feature that helps deal with markers that are close together or overlap because they share (almost) the same latitude / longitude.

The built-in “Overlapping Marker Spiderfier” makes markers fan out (“spiderfy”) into a circle with spokes, on click. Larger numbers (more than 8) fan out into a more space-efficient spiral.

Overlapping Marker Spiderfier plays nice with marker clustering: once you get down to a zoom level where individual markers are shown, these markers then spiderfy.

You may need to adapt the maxZoom parameter on the clusterer though, to ensure that it doesn’t cluster close markers all the way to the level that spiderfying would be more helpful behavior.

Customize Overlapping Marker Spiderfier

The Overlapping Marker Spiderfier library that FacetWP uses, has several useful options that determine how the ‘spider parts’ look and behave.

For example, setting the keepSpiderfied option to false overrides the default behavior where the spiderfied markers stay ‘spiderfied’ when you click a marker.

And the circleSpiralSwitchover option sets the number of markers at which the marker configuration turns into a spiral instead of a circle.

You can also set the leg length, leg thickness and several spiral properties. The code below shows some examples:

add_filter( 'facetwp_map_init_args', function( $args ) {

  if ( isset( $args['config']['spiderfy'] ) ) {

    // 'Unspiderfy' when clicking a 'spiderfied' marker
    $args['config']['spiderfy']['keepSpiderfied'] = false; // (FacetWP's) default: true

    // Do not 'unspiderfy' when clicking an empty spot on the map
    $args['config']['spiderfy']['ignoreMapClick'] = true; // default: false

    // Set the pixel radius within which a marker is considered to be overlapping a clicked marker.
    $args['config']['spiderfy']['nearbyDistance'] = 30; // default: 20

    // Switch from circular to spiral above 11 markers instead of above 8
    $args['config']['spiderfy']['circleSpiralSwitchover'] = 11; // default: 8

    // Set spider leg length when circular
    $args['config']['spiderfy']['circleFootSeparation'] = 40; // default: 23

    // Set spider leg length and other settings when spiral
    $args['config']['spiderfy']['spiralFootSeparation'] = 40; // default: 26
    $args['config']['spiderfy']['spiralLengthStart']    = 15; // default: 11
    $args['config']['spiderfy']['spiralLengthFactor']   = 6; // default: 4

    // Set spider leg thickness
    $args['config']['spiderfy']['legWeight'] = 3; // default: 1.5

  }
  return $args;
} );

Note that the FacetWP Map facet sets the following options to true by default, overriding the defaults mentioned in the Overlapping Marker Spiderfier library’s documentation:

// FacetWP Map facet Spiderfier defaults:
'spiderfy' => [
  'markersWontMove'   => true,
  'markersWontHide'   => true,
  'basicFormatEvents' => true,
  'keepSpiderfied'    => true
]

Customize spider leg colors

The following example shows how to set the color and highlight color of the spider legs. The colors need to be set for each map type separately. This examples only sets the colors for the ROADMAP map type. See the defaults and map type options here.

<?php
add_action( 'wp_footer', function () {
  ?>
    <script>
      (function ($) {
        $(document).on('facetwp-loaded', function () {
          if ('undefined' === typeof FWP_MAP) {
            return;
          }
          var mti = google.maps.MapTypeId;
          FWP_MAP.oms.legColors.usual[mti.ROADMAP] = '#cc52ab'; // Normal leg color. Default: '#444'
          FWP_MAP.oms.legColors.highlighted[mti.ROADMAP] = '#6233ca'; // Highlight leg color. Default '#f00'
        });
      })(jQuery);
    </script>
  <?php
}, 100 );

Map marker hooks and functions

FacetWP provides several JavaScript hooks and functions to perform actions when markers are interacted with, or to perform actions on markers when post (titles) in the result listing are clicked.

Example 1: Add a class to the post which has its marker clicked

The following example adds the CSS class is-active to the active post (the post which has its corresponding marker clicked), which could be used to style it differently than the other posts:

<?php
add_action( 'wp_footer', function() {
  ?>
    <script>
      (function($) {
        FWP.hooks.addAction('facetwp_map/marker/click', function(marker) {
          /**
           * The post ID associated with the active marker
           */
          var post_id = marker.post_id;
          /**
           * The following code adds the CSS class "is-active" to the active post,
           * assuming each result's HTML is structured similarly to:
           * <div class="post-item" data-id="123">Hello World!</div>
           */
          $('.post-item').removeClass('is-active');
          $('.post-item[data-id="' + post_id + '"]').addClass('is-active');
        });
      })(jQuery);
    </script>
  <?php
}, 100 );

The above example assumes your posts (or post titles) have a class post-item and a data-id attribute containing the post ID. One way to accomplish this is by using the Listing Builder’s Dev mode and adding the following code to the “Display Code” field:

<?php while ( have_posts() ): the_post(); ?>
<h3><a href="<?php the_permalink(); ?>" class="post-item" data-id="<?php the_id(); ?>"><?php the_title(); ?></a></h3>
<?php endwhile; ?>

Example 2: Open a marker’s infoWindow on mouse hover

In addition to the click event, FacetWP also supports mouseover and mouseout events.

This example opens a marker’s infoWindow on mouse hover:

<?php
add_action( 'wp_footer', function() {
  ?>
    <script>
      (function($) {
        FWP.hooks.addAction('facetwp_map/marker/mouseover', function(marker) {
          FWP_MAP.infoWindow.setContent(marker.content);
          FWP_MAP.infoWindow.open(FWP_MAP.map, marker);
        });
      })(jQuery);
    </script>

  <?php
}, 100 );

Example 3: Trigger a marker click and infoWindow on post click

The get_post_markers() function can be used to get markers by post ID and perform actions on them.

The following example triggers a marker click when you click on a post in the results list. It sets the map center to the marker’s position, opens its infoWindow and sets a custom zoom level.

Make sure that the zoom level is higher than the marker clusterer’s bottom limit, otherwise the separate markers will not be shown.

The click event to use is spider_click because of the built-in Overlapping Marker Spiderfier. If you don’t have any markers close together, you can also use the click event.

<?php
add_action( 'wp_footer', function () {
  ?>
    <script>
      (function($) {
        $(document).on('click', '.post-item', function(e) {
          e.preventDefault(); // Necessary if '.post-item' is an <a> tag and you don't want it to open the post page itself.
          var postid = $(this).attr('data-id');
          var marker = FWP_MAP.get_post_markers(postid);
          $.each( marker, function( key, value ) {

            FWP_MAP.map.setCenter({
              lat: value.position.lat(),
              lng: value.position.lng()
            });
            FWP_MAP.is_zooming = true; // Needed if you are using the "Enable map filtering" button
            FWP_MAP.map.setZoom(17); // Set a zoom level between 1 and 20. Make sure it is higher than the marker clusterer's bottom limit.

            // google.maps.event.trigger(value, 'click'); // If you don't have spiderfied markers
            google.maps.event.trigger(value, 'spider_click'); // If you have spiderfied markers. Will also work if you don't have spiderfied markers.

          });
        });
      })(jQuery);
    </script>
  <?php
}, 100 );

The above example assumes your posts items (or post titles) have a class post-item and a data-id attribute containing the post ID. See example 1 above to see how to accomplish that with the Listing Builder’s Dev mode.

More examples

Changelog

1.0

  • Improved refactored the "Enable map filtering" logic slightly
  • Improved support changing the spiderfier init arguments
  • Improved updated (and patched) markerclusterer.js
  • Improved renamed "Default lat / lng" to "Fallback lat / lng / zoom" for clarification
  • Fixed cleared up google `addDomListener` console warnings
  • Fixed make sure lat / lng aren't empty during indexing

0.9.3

  • Improved FacetWP 3.9 compatibility

0.9.2

  • Improved removed jQuery dependency

0.9.1

  • New added "Ajax marker content" UI option to choose between ajax-loaded and preloaded markers
  • Fixed switched from `init` to `facetwp_init` hook to prevent timing issues

0.9

  • Improved significant performance boost (esp. for maps with many markers)

0.8.1

  • Fixed issue causing "maxZoom" JS error

0.8

  • Changed use `FWP()->filtered_post_ids` if available
  • Fixed prevent infinite refresh when "Enable map filtering" is on

0.7.1

  • Fixed only load posts if the "Marker Content" box is filled (performance boost)

0.7

  • New `facetwp_map/fit_bounds` JS hook to disable fitBounds and manually center the map
  • Improved immediately trigger a refresh when the "Enable filtering" button is clicked
  • Improved replaced GMaps "scrollWheel" setting with "gestureHandling"

See also