October 18, 2017

Google Maps & Drupal: Getting Started

Written by Ellen Doornbos

Share on LinkedIn

So you want to build a map, but you don't know where to start? Let's take a tour of Drupal's contributed modules that integrate with Google Maps APIs. 

Collecting and Geocoding Addresses

Before we start looking at APIs, we'll need to collect some location data. There are plenty of ways to store geographical data in Drupal. In the context of a Drupal 7 project, we recommend using these four contributed modules together: Addressfield, Geocoder, GeoPHP, and Geofield

Addressfield allows us to collect and store postal addresses in a field type called "Postal Address." Geofield provides a separate field type for storing geographical data, such as latitude and longitude. The magic happens in the middle, when Geocoder gets these two fields talking to one another. Geocoder supplies a widget called "Geocode from another field." If we apply this widget to our field of type Geofield, we can fetch accurate coordinate data from any Addressfield. 

Check out this handy tutorial for a step by step demonstration of how these four modules interact. 

Displaying a Map Using a Contributed Module

Now that we have raw coordinate data, we'll need to find a way to display it. A common approach for displaying a map in Drupal is to provide a field formatter. We can download and enable such a contributed module, and apply its field formatter to our geographical data field (i.e. Geofield).

It's easy to become overwhelmed by the number of options out there. This Drupal.org article gives us a synopsis of choices. It's a lot, right? This list is by no means exhaustive either. If you're going to implement a contributed module on the front end, it's important to consider the stability, availability, and features it provides. Will you need to customize your map heavily to match a brand's look? What type of mobile experience do you want to offer? Consider also the user experience you're trying to craft.

Handling Keys

Keep in mind as you're browsing contributed modules: As of June 2016, Google Maps APIs no longer allow unregistered (keyless) access. There's no guarantee an older Drupal module has support for this. Some modules do, some don't, and some have adapted in light of Google's updated rules.

Geofield Maps is an interesting case study of an older Drupal module changing in the current landscape. As a submodule of Geofield, it hasn't seen a stable Drupal 7 release since 2014, but its users came together in the issues queue to develop a fairly stable patch for handling Google API keys. It's pretty neat to see the open source community responding to these sorts of demands. Ultimately, however, you want to choose a module that provides this type of support right out of the box. 

Customizing with Google Static Maps API

Let's say you're interested in building your own custom field formatter, but you don't have much experience with Google's APIs. Google Static Maps API is a great place to start. This API generates a non-interactive map - no zoom, no search, just a static image. Simply create a URL that conforms to the API's syntax, and place it in the src attribute of an <img> element. It's lightweight, easy to learn, and requires no JavaScript to use. 

On the Drupal side of this integration, we first implement hook_field_formatter_info(). Declare an array of field types for which your formatter is available. In this case, we want to manipulate the display of our Geofield data.

function MYMODULE_field_formatter_info() {
  $field_formats = array();
  $field_formats['my_formatter_machine_name'] = [ 
    'label' => t('My Custom Map Formatter'),
    'field types' => array('geofield'),
  ]; 
  return $field_formats;
} 

Next we're going to implement hook_field_formatter_view(). Iterate over all the items being viewed which have your custom field format. Build a render array for each item and append it to $element.

function MYMODULE_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array(); 

  if ($display['type'] == 'my_formatter_machine_name') {
    foreach ($items as $delta => $items) {
      $element[$delta] = array();
      $element[$delta]['#markup'] = '<img src="' . _MYMODULE_build_map_url($item) . '"></img>';
    }
  }

  return $element;
} 

Finally, let's create a helper function that will store all of our Google integration logic. Refer to the Google Static Maps API documentation for all the different key-value-pairs it allows.  

function _MYMODULE_build_map_url($item) { 
  $str = '';
  $str .= [Build your URL with key value pairs here! And in subsequent lines...];

  return $str;
} 

We'd love to chat about your next web or application project!