Grunzer Logo (Piggy Nose) grunzer

WordPress Headless

Wordpress built-in REST API: Key Concepts

Getting Started

WordPress provides a REST API to site content by default on a new installation, so there is nothing special to setup. You can basically just use it out of the box.

You can access the JSON api using the following base URL:

API Base URL: <site-url>/wp-json

Blog Posts

Endpoint: GET /wp-json/wp/v2/posts

API Reference

Pages

Endpoint: GET /wp-json/wp/v2/pages

API Reference

Exposing Gutenberg Content Blocks

Normally the page or blog post content is served in rendered state. That means you cannot access content blocks and their respective attributes.

The normal result for a page would look like this:

{
  "title": {
    "rendered": "My Page Title"
  },
  #...
  "content": {
    "rendered": "<h2>Heading</h2><p>text</p>"
  }
  #...
}

To access the raw data you can set the context query parameter to edit like this:

/wp-json/wp/v2/pages?context=edit

Defining context in the WP REST API

But even the raw data is not really usable:

{
  "title": {
    "raw": "My Page Title",
    "rendered": "My Page Title"
  },
  #...
  "content": {
    #...
    "raw": "<!-- wp:heading -->\n<h2>Heading</h2>\n<!-- /wp:heading -->\n\n<!-- wp:paragraph -->\n<p>text</p>\n<!-- /wp:paragraph -->"
  }
  #...
}

So how do we actually expose the content blocks of the gutenberg editor?

At the time of writing there seem to be no other way than adding some extra plugin which adds the missing blocks to the API.

We can do this by adding a rest_api_init hook and add a blocks property to the json. Check the following article from wpscholar and copy the php snippet: Surfacing Gutenberg Blocks in the WordPress REST API.

You can add this snippet as extra plugin in /wp-content/plugins but for a quick test you can also add it to an exisiting plugin. I just appended the code to the default "Hello Dolly" plugin by using the Plugin Editor in WordPress. Make sure to activate the plugin.

Now your output should look like this:

{
  #...
  "content": {
     #...
   },
   blocks: [
       {
            "blockName": "core/heading",
            "attrs": {
                "level": 4
            },
            "innerBlocks": [],
            "innerHTML": "\n<h4>Heading H4</h4>\n",
            "innerContent": [
                "\n<h4>Heading</h4>\n"
            ]
        },
        {
            "blockName": null,
            "attrs": [],
            "innerBlocks": [],
            "innerHTML": "\n\n",
            "innerContent": [
                "\n\n"
            ]
        },
        {
            "blockName": "core/paragraph",
            "attrs": [],
            "innerBlocks": [],
            "innerHTML": "\n<p>test</p>\n",
            "innerContent": [
                "\n<p>test</p>\n"
            ]
        },
   ]
  #...
}

That is what we actually wanted to have! Now we can add a custom frontend with react, vue or angular and just run wordpress headless. There might be data missing in the block data but you can easily customize this output by modifing the plugin.