I had a special case today where I needed to pull in posts specifically from a Yoast SEO Plugin‘s primary category. Yoast SEO allows you to set a single, primary category for a post in WordPress. This is an awesome feature and very useful.
A site I’m building right now uses the API to pull in the latest articles of a category in a big drop down hero navigation system. The thing is, just pulling from a category gets a lot of the same articles when clicking around the different category options. We wanted to pull by primary category so each click gives a unique set of posts that are very relevant to the category option.
The Struggle
There may be a super simple way to do this already but I was seriously struggling googling for the answer. I’ve done some extending of the WP REST API but I’m still a novice so I was hoping to avoid it. But glad I didn’t because I learned a lot and I made a cool thing!
I couldn’t find a function in Yoast that pulled post IDs or anything based on a primary category. I needed to figure out how they assigned this. I dug through the database and found a post meta with the key ‘_yoast_wpseo_primary_category.’ This is it, this is what I’ll use to build my end point.
The Code
First we need to register our endpoint/route. I prefer building things in classes so I created a class:
<?php
class Rest_Api_Posts_By_Primary_Category {}
I register the endpoint in the __construct() as so:
https://gist.github.com/ChrisFlannagan/a6f63a02ea16268a25bc5d386e9ac63a#file-primary-cat-part-1-php
SITE_PREFIX is something I set in my theme’s functions.php file. You need a namespace here so make it unique based on your plugin or theme or site in general.
The callback function is where the magic happens. In get_posts_by_primary_cat( $data ) we do a simple WP_Query that makes use of the meta_query ability. The thing is, I need the children of categories too. Here’s an example similar to what I’m dealing with.
Let’s say we have three categories and these categories are what we see in our navigation menu: Math, Reading, History
Then those categories each have two children: ###-Lessons, ###-Research
So our final category structure looks like
Math
– Math-Lessons
– Math-Research
Reading
– Reading-Lessons
– Reading-Research
History
– History-Lessons
– History-Research
If someone clicks Reading I want to load all posts that have a primary category of Reading, Reading-Lessons or Reading-Research… so I need the children.
In the function below you can see I run get_categories on the selected category withe parent argument assigned. This gets me all the children. I just need their ids and I need them in string format so I run a quick foreach loop. I make sure to add the original parent id back to the new array too. Then I run the WP_Query.
https://gist.github.com/ChrisFlannagan/a6f63a02ea16268a25bc5d386e9ac63a#file-primary-cat-part-2-php
At this point you could just return $posts->posts but I needed the featured image and only a few of the pieces like title, time and a link. So I built out what I need and return that.
Conclusion
Now to use this we simply visit http://yoursite.com/wp-json/SITE_PREFIX/v1/yoastprimary/##-catid-## and replace ##-catid-## with the actual category number. I could’ve just made this a static class now that I think about it but whatever, you must remember to initiate it to work. So in your functions.php of the theme or somewhere in your plugin call $rest_api_primary_cat = new Rest_Api_Posts_By_Primary_Category();
This was easy to parse in my javascript and is running great. Hope it helps someone! Here’s the full code:
https://gist.github.com/ChrisFlannagan/a6f63a02ea16268a25bc5d386e9ac63a#file-primary-cat-php