IDEAS | BLOG

Using D3 and AJAX in WordPress

Having worked professionally as a Drupal developer since 2007, I can confidently say I know the ins-and-outs of that platform. Yet I've never had the opportunity to do much serious work in WordPress. So starting this past summer I was excited when the opportunity came for me to plunge into WordPress – by building my very first site on this popular open-source platform.

The project was to redesign a site for BlueCross BlueShield of North Carolina Foundation, a prominent healthcare foundation that awards grants for groups working to improve health for the citizens of North Carolina. It was a promising project with the cool opportunity to shift the organization to new and more capable technologies for data visualization, so I eagerly rolled up my sleeves and got to work.

Moving from Flash

As a key priority, the client wanted to modernize a Flash-based feature that allowed users to browse information about previously awarded grants by county. Because the new site is mobile-friendly, this was the perfect opportunity to ditch the old Flash technology in favor of a JavaScript approach. Here's what the old map looked like:

d3

Migrating the Data, Shifting the Tech

The first step was to migrate data from the old site featuring 600+ grant programs that the foundation had awarded in the last 14 years. The grant data already included geographic information, so it was simple to create individual “grant” posts within WordPress and feed the county information into a new custom field using Custom Post Types and the Custom Field Suite (the latter plugin being one developed by my awesomely talented colleague, Matt Gibbs). Next, we used D3 to create a county map for the state in which the foundation works. A Google search turned up a geojson file containing all the data we needed to create the map. We built a custom page template to house our map-specific HTML markup and added a function to our functions.php file to handle adding all of the necessary scripts to the page. With the basic map in place, we needed to provide users a way to select a county and see all past grants awarded there.  This required a call to the database, which we did via AJAX, bound to the click event:

$.ajax({
  url: PT_Ajax.ajaxurl,
  data: {
    action: 'f1ux_get_county_posts', // Name of PHP function
    county: county // The county argument received from the click event handler
  },
  success: function(data) {
    // Populate HTML elements with the data
  },
  error: function(error) {
    // Populate an error message
  }
});

When working with AJAX in WordPress, you have to tell WordPress in your functions.php file that you will be making an AJAX call. First, you must implement wp_localize_script() with the name of the calling script:

function f1ux_add_map_files() {
  wp_localize_script('grantee-map', 'PT_Ajax', array('ajaxurl' => admin_url( 'admin-  ajax.php')));
}

Then, you call add_action() to register the function calling wp_localize_script() and the name of the PHP functions your AJAX script wants to use:

add_action( 'wp_enqueue_scripts', 'f1ux_add_map_files' );
add_action( 'wp_ajax_f1ux_get_county_posts', 'f1ux_get_county_posts' );
add_action( 'wp_ajax_nopriv_f1ux_get_county_posts', 'f1ux_get_county_posts' );

If your AJAX call can be made by both authenticated and logged out users, you must include both lines 2 and 3 in the snippet above.   With this code in place, each time a user clicks on a specific county, an AJAX request would be fired that hit a custom PHP function (f1ux_get_county_posts($county)). That function queries the WordPress database for all posts associated with that county, and returns a JSON object containing the title and url of each post.

function f1ux_get_county_posts() {
  $county = $_REQUEST['county']; //Passed from JS
  $posts = array();

  // Grab the grantee profiles related to this county
  $query = new WP_Query(
    array(
      'post_type' => 'grantee',
      'posts_per_page' => -1,
      'orderby' => 'meta_value',
      'meta_key' => 'date_awarded',
      'meta_query' => array(
        array(
         'key' => 'county',
         'value' => $county,
         'compare' => '='
        )
      ),
    )
  );

  if ($query->have_posts()) {

    while ($query->have_posts()) {
      $query->the_post();
      $list['profiles'][] = array(
        'title' => get_the_title(),
        'href' => post_permalink(),
      );
    }
  }
 
  $response = json_encode($list);
  header( "Content-Type: application/json" );
  echo $response;
  exit;

}

The JS script iterates over the response and writes it to the DOM. This is an example of our end result:

d3

And finally, to improve usability on mobile devices, we made a small modification to our script to generate a form select in place of the map, because the county targets would prove difficult for users to tap at small resolutions. In that case, the AJAX script is triggered on a change event for the select element instead. To the right is an example of how users can now find grantees using their mobile devices:

d3

As you can see, shifting to new technology not only improved the overall usability of the map, but it also finally made it accessible and usable for the growing segment of users who visit the site with their mobile devices. This project was a fun and rewarding opportunity for me to port my experience over to WordPress while breathing new life into a valuable data visualization for the citizens of North Carolina. Go ahead and test drive the grantee map yourself! As for me, I'm looking forward to the next opportunity to broaden my skills and sharpen my WordPress chops on a future project at Forum One.