Using the WP-API to Fetch Posts

Avatar of Andy Adams
Andy Adams on (Updated on )

📣 Freelancers, Developers, and Part-Time Agency Owners: Kickstart Your Own Digital Agency with UACADEMY Launch by UGURUS 📣

It may be news to you, but there is a nifty resource called Quotes on Design that serves up interesting quotes about design, curated by our very own Chris Coyier.

Up to this point, Quotes on Design (QoD) used a bit of custom code to query the WordPress database and serve up quotes. This was used for the site itself, and for its API to allow use on external sites. With the excitement surrounding the upcoming WordPress JSON REST API, we thought it would be fun to rebuild the site to use the WP API instead of our own custom code.

Here’s what we’ll cover:

  1. Setting up the API
  2. Querying the API to grab a random quote
  3. Doing something interesting with that quote
  4. Customizing the API to remove unused information
  5. Using the new QoD JSON REST API to grab nifty quotes for your site

Warning! The WP JSON REST API is still in development, and the query interface could change before the final version. We’ll do our best to update this tutorial if anything changes. We wouldn’t recommend using the WP API on any super-important sites just yet, unless you’re a ultra-professional WordPress developer, in which case you probably can skip this article, right?

Installing the WP API

The WP API is packaged as a plugin, available on the WordPress.org plugin repository. That means you can

  • Open your WordPress dashboard
  • Go to Plugins → Add New
  • Search for “WP API”
  • Install, activate, and you’re done

Let’s start digging in!

Grabbing a random post

For QoD, we wanted to add some simple functionality to the home page: Click a button, and have a random quote reloaded from the API.

The WP API includes several endpoints you can use to read information from the database, including meta, attachments, users – really, anything that is stored in the standard WP database is accessible to some degree.

For our use case, we just needed to grab a random post. We started with the /wp-json/posts endpoint, which is essentially like running a WP_Query, if you’re familiar with WordPress development. Here’s the base endpoint URL:

http://quotesondesign.com/wp-json/posts

Visiting that URL without any query parameters returns the default list of posts in JSON format — essentially, the same list of posts you’d see on the blog page:

[
  {
    "ID": 2328,
    "content": "<p>Everything we do communicates.</p>\n",
    /* ...snip most of the fields... */
    "title": "Pete Episcopo",
    "type": "post"
  },
  {
    "ID": 2326,
    "content": "<p>The only &#8220;intuitive&#8221; interface is the nipple. After that it&#8217;s all learned.</p>\n",
    /* ...snip most of the fields... */
    "title": "Bruce Ediger",
    "type": "post"
  },
  {
    "ID": 2323,
    "content": "<p>Only show work you like, or you&#8217;ll end up being hired to do things you don&#8217;t like.</p>\n",
    /* ...snip most of the fields... */
    "title": "Victoria Pater",
    "type": "post"
  }
]

Note that the IDs of the quotes are sequential: they represent the three most recent quotes on the site.

For our design, we only need one post and we want it to be randomly selected. We need to filter the results, and we can do this using the same arguments we would use when calling WP_Query or get_posts.

In this case, we need two arguments:

  • The orderby argument needs to be rand, to fetch a random post
  • The posts_per_page argument needs to be 1, to limit the results to a single post

See a list of all available parameters on the WP_Query codex entry.

We pass those arguments through the URL, using the filter query variable as an array, like so:

http://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1

Here’s what we get back from the WP API using our filtered URL:

[
  {
    "ID": 2153,
    "author": {
        "ID": 2,
        "URL": "https://css-tricks.com",
        "avatar": "http://0.gravatar.com/avatar/8081b26e05bb4354f7d65ffc34cbbd67?s=96",
        "description": "",
        "first_name": "Chris",
        "last_name": "Coyier",
        /* ...snip some fields... */
    },
    "comment_status": "closed",
    "content": "<p>Wonderfully designed > beautifully designed. Any day.</p>\n",
    "date": "2013-06-27T08:34:04",
    "date_gmt": "2013-06-27T16:34:04",
    "date_tz": "Etc/GMT-8",
    "excerpt": "<p>Wonderfully designed > beautifully designed. Any day.</p>\n",
    "featured_image": null,
    "format": "standard",
    "guid": "http://quotesondesign.com/?p=2153",
    "link": "http://quotesondesign.com/daniel-burka-2/",
    "menu_order": 0,
    "meta": {
        /* ...snip some fields... */
    },
    "modified": "2013-06-27T08:34:04",
    "modified_gmt": "2013-06-27T16:34:04",
    "modified_tz": "Etc/GMT-8",
    "parent": null,
    "ping_status": "closed",
    "slug": "daniel-burka-2",
    "status": "publish",
    "sticky": false,
    "terms": {
      /* ...snip some fields... */
    },
    "title": "Daniel Burka",
    "type": "post"
  }
]

Every time we refresh our filtered URL, we’ll get a different quote. Sweet!

You’ll notice that I’ve included more of the WP API JSON response in the last snippet. There’s a lot of information there — even when I hide the meta, author and terms.

For our purposes, we don’t need most of that information. Plus it’s more bandwidth-efficient to not include it all – so let’s chop it out!

Removing fields from the JSON response

A reader wrote it to say you don’t have to do this all anymore as there is a _filter argument in the API now.

We need to filter the data being returned by the API, and fortunately the WP API provides us with exactly the filter we need, called json_prepare_post. To use it, we create a new plugin with the following snippet of code:

function qod_remove_extra_data( $data, $post, $context ) {
  // We only want to modify the 'view' context, for reading posts
  if ( $context !== 'view' || is_wp_error( $data ) ) {
    return $data;
  }
  
  // Here, we unset any data we don't want to see on the front end:
  unset( $data['author'] );
  unset( $data['status'] );
  // continue unsetting whatever other fields you want

  return $data;
}

add_filter( 'json_prepare_post', 'qod_remove_extra_data', 12, 3 );

Activating our plugin leaves us with a much smaller JSON response, which only contains the info we need for our use case:

[
  {
    "ID": 686,
    "content": "<p>My secret is being not terrible at a lot of things.  </p>\n",
    "link": "http://quotesondesign.com/moby/",
    "title": "Moby"
  }
]

Adding fields to the JSON response

Now that we’re done removing unnecessary information from the JSON data, it’s only fitting that we add some of our own custom fields to stay balanced. Wax on, wax off.

Some of the quotes have a custom meta field called “Source”, which Chris uses to link to the original source of the quote, if it is available online. Let’s add that meta data to the JSON response using the same json_prepare_post filter we used to remove data previously. In the same plugin, we add the following function:

function qod_add_custom_meta_to_posts( $data, $post, $context ) {
  // We only want to modify the 'view' context, for reading posts
  if ( $context !== 'view' || is_wp_error( $data ) ) {
    return $data;
  }

  $source = get_post_meta( $post['ID'], 'Source', true );

  if ( ! empty( $source ) ) {
    $data['custom_meta'] = array( 'Source' => $source );
  }

  return $data;
}

add_filter( 'json_prepare_post', 'qod_add_custom_meta_to_posts', 10, 3 );

With that extra field appended, here’s what a JSON response looks like:

[
  {
    "ID": 2039,
    "content": "<p>Communication that doesn&#8217;t take a chance doesn&#8217;t stand a chance.</p>\n",
    "custom_meta": {
        "Source": "<a href="http://altpick.com/spot/segura/segura.php">article</a>"
    },
   "link": "http://quotesondesign.com/carlos-segura/",
    "title": "Carlos Segura"
  }
]

Now that we have exactly the information we need, let’s use the JSON API to load a random quote via AJAX on the home page.

Fetching and using data from the JSON API

On the homepage of QoD, we have a button to grab another quote:

Get Another Quote Button

Using jQuery event handlers and the jQuery.ajax function, we grab a quote and update the HTML with the following snippet:

jQuery( function( $ ) {
  $( '#get-another-quote-button' ).on( 'click', function ( e ) {
    e.preventDefault();
    $.ajax( {
      url: '/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1',
      success: function ( data ) {
        var post = data.shift(); // The data is an array of posts. Grab the first one.
        $( '#quote-title' ).text( post.title );
        $( '#quote-content' ).html( post.content );

        // If the Source is available, use it. Otherwise hide it.
        if ( typeof post.custom_meta !== 'undefined' && typeof post.custom_meta.Source !== 'undefined' ) {
          $( '#quote-source' ).html( 'Source:' + post.custom_meta.Source );
        } else {
          $( '#quote-source' ).text( '' );
        }
      },
      cache: false
    } );
  } );
} );

Now, when the button is pressed a new random quote is automagically loaded. Try it out.

Using the API on your site

You can query Quotes on Design using the API to show nifty quotes for your own site. We’ve updated the API page to use the new WP JSON API. As mentioned earlier, the WP API is subject to change, so don’t rely on this API for uber-important sites just yet.

More API goodness is coming

Development on the WP API is ongoing, and there is a lot of excitement to see what folks can build with it. Our example is pretty basic, but the thought of a JSON API has already gotten our gears turning about the possibilities.

Check out Quotes on Design and share your thoughts and questions in the comments. And if you have a great quote you’d like to see on the site, submit it!