tetchi blog

Tetchi's blog about life and stuff

How to post comments using the WordPress REST API

WordPress logo

A quick tutorial on how to use the WordPress REST API to post comments asynchronously.


I recently converted my WordPress blog into a headless, Gatsby-powered site, and one of my requirements was to have a working comment form. I knew this was possible using the WordPress REST API but I didn’t find the documentation very helpful and was not able to find any good examples. I decided to document the steps I took to make a working comment form for my blog with the hopes of helping others looking to do a similar thing.

The example in this post uses React JSX, but the code can easily be applied to a regular PHP-based WordPress site that uses vanilla JavaScript.

You can see a quick video of the comment form in action below. Or, you can also try it out by using the comment form at the bottom of this page 😊.

Posting a comment asynchronously with the WordPress REST API.

1. Open Inspector’s Network tab

First thing’s first, let’s open up Chrome’s Network tab for debugging. This handy tab will tell us if the comment was submitted properly and about any errors we might get. Other browsers should have a similar tab, but for the purpose of this tutorial I’m going to stick with Chrome.

2. Enable anonymous comments

Before we create the form, we have to enable anonymous comments on your WordPress theme. This is done by enabling the
rest_allow_anonymous_comments hook.

Open your WordPress theme’s functions.php, and add the following snippet:

  add_filter( 'rest_allow_anonymous_comments', '__return_true' );

If you skip this step and try to post a comment using the REST API, you will get a 401: Sorry, you must be logged in to comment. error.

Shoutout to @websupporter for this tip!

3. Create a form

The next step is to create the comment form. Since I’m using Gatsby, the code example below is in React JSX, but you can convert it to be plain old HTML.

<form>
  <input type="hidden" id="postId" value={POST_ID} />
  <div>
    <label htmlFor="name">Name*</label>
    <input id="name" type="text" required />
  </div>
  <div>
    <label htmlFor="email">Email*</label>
    <input
      id="email"
      type="email"
      required
    />
  </div>
  <div>
    <label htmlFor="comment">Comment*</label>
    <textarea
      id="comment"
      required
    />
  </div>
  <input type="submit" value="Post comment!" />
</form>

The form must contain the following information:

  • post ID (usually a four digit number, ex: 4583)
  • comment author’s name
  • comment author’s email
  • content for the comment

In my case, I’m passing the post ID as a prop from my template that handles all of the GraphQL queries. If you’re working in PHP, I believe you can use <?php the_ID(); ?> to get the post ID.

Other details such as the date and IP address are filled out automatically so you shouldn’t need to pass those into the form. For the IP address, you’ll see something like ::1 on your local WordPress instance, but on your production site you should see the actual IP address of the comment author.

4. Create a handler for your form

Add an onSubmit handler to the <form>.

<form onSubmit={this.handleSubmit.bind(this)}>
  <input type="hidden" id="postId" value={POST_ID} />
  <div>
    <label htmlFor="name">Name*</label>
    <input id="name" type="text" required />
  </div>
  ...
  ...

Finally, let’s add the code for the handler.

handleSubmit(evt) {
  evt.preventDefault();

  const [postId, name, email, comment] = evt.target.elements;

  const data = JSON.stringify({
    post: postId.value,
    author_name: name.value,
    author_email: email.value,
    content: comment.value,
  });
  
  // ACTION_URL = "https://your-wordpress-site.com/wp-json/wp/v2/comments"
  fetch(ACTION_URL, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json',
    },
    body: data,
  })
    .then((response) => {
      if (response.ok === true) {
        // Submitted successfully!
      }

      return response.json();
    })
    .then((object) => {
      // Comment submission failed.
      // Output `object.message` to see the error message.
    })
    .catch(error => console.error('Error:', error));
}

Here’s a quick breakdown of what’s happening:

  1. Do preventDefault() to prevent the form from submitting
  2. De-structure postId, name, email, and comment from event.target.elements
  3. Do a fetch to post to ACTION_URL (this is the /wp-json/wp/v2/comments endpoint of your WordPress blog).
  4. Once we receive the response, check for the value of response.ok.
    1. If true, the comment was submitted successfully. Otherwise, run response.json(), which returns a promise.
  5. Once the promise is resolved, we receive an object which gives us all sorts of details about what went wrong. You can output object.message to see the message that was returned from WordPress.

That’s it! You should now have a working, basic WordPress comment form that posts comments using the REST API. You can check out the code for the more complete version (including states for buttons, error messages, etc.) here – it may be useful to see it in a React/Gatsby context.

Please leave a comment if you have any questions or advice!

3 Comments

  • test
    test on June 24th, 2019

    test comment

  • Testing
    Testing on August 13th, 2019

    Testing Comment

  • Hanna Haritha valli
    Hanna Haritha valli on August 20th, 2019

    ghj

Post a comment