Using the Wordpress REST API with React.js

It'd been a few (happy) years since I last used Wordpress for a client project, but with its now (questionably-)stable REST API it came up last year as a potential candidate for backing a React-based magazine/news site. After doing some digging it became clear that it was not only a possible candidate, but a frontrunner amongst the options as it would provide ~80% of what we needed with minimal work, potentially providing huge time and cost savings to our client.

Unfortunately, its cryptic documentation left something to be desired and most articles around the web were either for v1.x, out of date with current v2.x changes, or just plain wrong. So as usual with Wordpress, it was up to us to sort out that other 20% for ourselves.

Adding Endpoints for Custom Post Types

In our project's case we are using the default Wordpress “Post” post-type for the bulk of the site's news and blog articles (sorted into categories), but needed to add Custom Post Types for our other content types like Events & Videos.

If you're familiar with adding Custom Post Types (CPTs) the snippet below for our “Events” CPT should look familiar (if not I recommend reading up on them first in the Wordpress Codex or on Elegant Themes' excellent guide to Custom Post Types). There's a lot going on this, but lines 35-37 are the specific part relevant to making the CPT accessible through the REST API.

Line 35 tells Wordpress to expose this CPT in the rest API (pretty self explanatory).

Line 36 gives the CPT a URL base within the API. Rather than query /wp-json/wp/v2/posts/ for a normal Post, this tells Wordpress you want to be able to query this CPT at /wp-json/wp/v2/events/. You can change this to be anything you want as long as it doesn't collide with another CPT or built-in post types (Post, Page, etc), though it generally makes sense to keep it the same as the CPT's name.

Line 37 tells Wordpress to extend the default WP_REST_Posts_Controller for functionality related to handling API calls. It's technically possible to heavily extend or customize this, but that's outside the scope of this article.

For our purposes we're using these CPT endpoints as read-only GET requests, but they can also be used for your standard POST/PATCH/DELETE requests if you setup an auth layer to verify those requests.

Adding Custom Metadata to API Responses

Now that we have a CPT setup we can query the API for a list of events, a single event, and more (all documented reasonably well here on the REST API Handbook). Unfortunately, if you're creating a CPT there's a good chance the default schema won't store everything you need and you'll need to customize the response to add additional fields. There's two ways of doing this that we explored and found as viable routes:

The Native Wordpress Way

To add additional fields without using a plugin you'll have to use the register_meta hook in your functions.php. This is documented here, but is formatted as register_meta(post_type, meta_field_name, array($args));. In our case wanted to add the city our event was taking place in (amongst other things):

register_meta('event', 'city', array(
     'type'         => 'string',
     'description'  => 'An string containing the city in which the event is taking place.',
     'single'       => true,
     'show_in_rest' => true
 ));
  • event is our custom post type from earlier, and city is the name of the metadata field we're adding.
  • type can be either a string, object, or integer.
  • description should be a plain English explanation for what the field is used.
  • single tells Wordpress that this meta field should be used on an individual (or “single”) post.
  • show_in_rest is what actually exposes the field on the API response.

Using Advanced Custom Fields (ACF) for Custom Metadata

The above way of registering custom metadata works well, but unfortunately left us with the issue of needing to either build custom metaboxes or having our client edit the content using the clunky default metaboxes, which wouldn't work for fields where there might be zero, one, or several repeating items depending on the “Event” — enter using ACF Pro.

ACF has been a staple of most Wordpress projects I've built in the past several years, and is one of maybe two or three plugins I can actively recommend using on a site[1]. It's extremely easy to setup and customize, and by default has a much improved editing experience for editors than the default Wordpress metaboxes. Unfortunately integrating it with the Wordpress REST API isn't officially supported just yet, and there wasn't a clear answer on the best way to add data input through ACF forms to each API response.

Adding the Featured Thumbnail to Single Post Responses

Oddly the Wordpress API only exposes the media ID for post‘s featured image rather than embedding it directly. While it would be pretty easy to get the image URL by querying the media endpoint after receiving the first response it seemed wasteful to make multiple API calls if it could be avoided, and this wouldn't scale well once we start showing lists of posts where they all have featured images. Enter the _embed query param.

This is briefly documented on the Linking & Embedding page of the API Handbook, but simply requires adding a ?_embed query param to the end of your request, so a GET request to /wp-json/wp/v2/events/ becomes /wp-json/wp/v2/events?_embed. It's not entirely clear why the Wordpress team has taken this approach, but it updates the response to include an attribute called wp:embedded on the response object, which includes all details about attached featured images.

Just be wary if you're fetching a large number of posts as this can balloon the JSON response size substantially.


  1. I otherwise avoid plugins at all costs as they tend to trade flexibility for stability, and are rarely written correctly. ↩︎