Customizing WordPress GraphQL with custom fields

If you've used WordPress for a while, and have ever wanted to add custom metadata to a post, such as a caption/subtitle for example, this can be done with something called "custom fields". However, enabling them in WordPress doesn't mean they're visible to a static site using GraphQL to fetch data from WordPress.

What is a static website?

A "static" site is a site made of code that doesn't change once it's built. Think of it as a book: after printing, the content doesn't change. This has many advantages over dynamic sites such as WordPress:

  • Speed: Since the content doesn't change, multiple copies of the site can be stored on multiple servers, so that the user gets served from the closest server, reducing latency.
  • Better SEO: As the content can be served served quicker without having to use javascript, your website can be higher up in search results
  • Security: The site doesn't contain databases visible to users which they potentially gain access to, and other vulnerabilities.

For a while, having a static site meant that whenever you want to change anything, you would have to manually go through each HTML file and edit each change manually. This has changed with the arrival of services such as Next.js and Gatsby, which can retrieve external data and create HTML files from them at build time.

I personally have a Next.js website with WordPress as the CMS. They interface with WPGraphQL, a plugin for WordPress creates a GraphQL API. GraphQL is an open source data query language originally developed by Facebook.

How to add custom fields in WordPress

Enabling custom fields is fairly simple. From the post editor, click on the three dots on the top right and head to Preferences > Panels.

The post editor preference pane

Once you do this, you need to reload the page to apply the changes, and the custom fields appear underneath the post content (I spent quite a while trying to find them in the sidebar, to no avail). There may already be a custom field or two, such as mine which has a classic-editor-remember field, to remember if I last used the WordPress block editor or the custom editor on my post, I believe.

Custom fields on the bottom of the page

Making custom fields visible to GraphQL

Once you've added your custom fields, it's time to make them visible to the GraphQL API. In a nutshell, GraphQL serves data through a type: each type has a set number of fields (these fields aren't the same as WordPress custom fields!) that can be populated so that you know what to expect in the data. For example, a post type could have the following fields:

  • Title
  • Content
  • Description
  • Author
  • Published date
  • Last modified date

In order to make the custom fields appear, the post type has to be changed to reflect the new field.

To do this, there's a bit of PHP involved to add this as a field type in GraphQL.

I found that the best way to do this was via the WordPress admin panel, by editing the theme PHP files with the Theme File Editor. To do this, go to Themes>Theme File Editor. I had the Hello Elementor theme preinstalled with my version of WordPress, which is of no importance since I only use the WordPress website as a CMS, the website part visible to users is implemented with Next.js.

The theme file editor

Next, go to the relevant functions.php file (in my theme it's called elementor-functions.php). This is where we're going to add the code relevant to adding a GraphQL field. I wanted to modify the post type to add a caption field.

This is the code I added to do so:

/* *
 * Custom fields for WP Graph QL
 * */
add_action( 'graphql_register_types', function() {
  register_graphql_field( 'Post', 'caption', [
     'type' => 'String',
     'description' => __( 'The caption of the post', 'wp-graphql' ),
     'resolve' => function( $post ) {
       $caption = get_post_meta( $post->ID, 'caption', true );
       return ! empty( $caption ) ? $caption : ";
  ] );
} );

Be careful modifying WordPress PHP files! If you do something wrong, it could muck up the whole site and prevent even the admin panel from showing, even something as small as a syntax error, such as a forgotten semicolon. Make sure you have a backup of your WordPress site before making any changes!

The function runs when GraphQL is compiling its types, and we're registering a new caption field to the post type. To fetch the data, we're querying the caption field on a WordPress post with a known ID, using the built-in function get-post-meta. Finally, if there is no caption on a given post, we return an empty string.

In order to test that the new field works on the post type, WPGraphQL comes with a built-in IDE to test queries. In the WordPress admin panel, head to GraphQL > GraphiQL IDE, and input the following query in the left pane:

query AllPosts {
  posts(first: 20, where: {orderby: {field: DATE, order: DESC}}) {
    edges {
      node {

The above code fetches the last 20 post ordered by date, and it fetches the title, excerpt, date and caption custom field. If everything works, it should retrieve the data and display any captions you've added to posts on the left pane when you click the "Play" button. If there is an error mentioning an unknown field type, it means the PHP code you entered for the custom field is not being recognized. This might mean that the functions.php file is the wrong file. I had two -functions.php files in my theme files, and the first file I added the code into resulted in an error, so I added it to the second file.

PHP Code – https://master–



Last edited:

Last edited:


More posts

Cover Image for Locate Website Visitors in Next.js with IP and Supabase

Locate Website Visitors in Next.js with IP and Supabase

Using an IP lookup API, a backend database and Next.js middleware, we’ll explore how to display the location of the last visitor on a website.

Cover Image for Making the Internet More Human

Making the Internet More Human

Navigating the internet has become difficult with all the accessibility issues, pop-ups, cookie banners and advertisements. We’ll explore different ways to make the web a more welcoming place for humans.