Easier editing for repetitive data in WordPress

photo of 5-story library building

Background

I’ve been the leader for my school’s robotics team’s website sub-team for the last two years. On our website, every student and alumnus gets their own webpage with some information about them, their name, their graduation year, etc.

A major part of the website sub-team’s responsibility is to create and update each student’s webpage every year. We use WordPress for the site, so it’s super easy for non-web-developers to update each student’s page.

Unfortunately, though, “ease of use” is a double-edged sword. All of the student pages are created as pages in WordPress, and everyone has to copy/paste a predefined template and fill in the blanks in the template every time they want to create a new student page. That’s how it has worked since our website was first established around 10 years ago.

What that method means is that every student page is a little inconsistent (e.g., if someone missed a letter while copying the template), and there’s no way to fix it across the site without manually checking hundreds of pages by hand. Not to mention, it’s incredibly tedious to create dozens of student pages each year for the new students that join our team. The new Gutenberg block editor has also meant that the template is even less readable in the WP code editor, being interspersed with random <p> tags and other non-human-parseable garbage. Not good!

Example of the template that has to be manually copy-pasted for every student page

Solution

In my opinion, the solution for this issue is to start using custom post types. As WPBeginner.com explains,

These are useful when creating content that has a different format than a standard post or page.

For example, if you run a book review website, then you would probably want to create a book reviews post type. This post type can even have different custom fields and a unique category structure.

https://www.wpbeginner.com/beginners-guide/when-do-you-need-a-custom-post-type-or-taxonomy-in-wordpress/

Sounds PERFECT for our use case!


On my testbench WordPress site, I developed a proof of concept for how a custom post type might be used to make the student page creation process easier.

I actually have past experience with custom post types – the very first version of GambitProfit used WordPress with a custom post type to store the sports games on the site. (I ended up moving to a custom-developed solution for GambitProfit because the WP-JSON API still doesn’t have good support for custom post types, making it very hard for me to automatically scrape sports games on the internet and post them on GambitProfit.)

Anyways, back to this site: First, I created a custom post type using the Pods plugin, which provides an easy-to-use GUI for creating and updating custom post types. (Normally, one would have to use WordPress’s register_post_type() function in the theme functions.php or a custom plugin.)

I also created a few fields for the new students custom post type to store the data associated with each student, including their name, their graduation year, a fun fact about them, etc. People on the website sub-team would only have to fill in these fields in a very simple form-based interface when creating or updating student pages (see the demonstration at the end of this post).

Then, I created a simple template to display each element stored as the new custom post type (i.e. a page for each student). It’s designed to very nearly replicate the template currently used so that end-users of our site don’t experience any changes in their viewing experience. It looks like this:

<p><b>Class of {@grad_year}</b></p>
 
<hr>
 
<p><b>Joined team in:</b> {@join_year}</p>
 
 
<p><b>Subteam(s):</b> {@subteam}</p>
 
<hr>
 
<p>
    <b>What are 2 fun facts about you?</b>
    <span>{@fun_facts}</span>
</p>
 
<p>
    <b>Why did you join the AdamBots?</b>
    <span>{@reason_joined}</span>
</p>
 
<p>
    <b>What is your favorite team memory?</b>
    <span>{@team_memory}</span>
</p>
 
<p>
    <b>What have you learned from being on the team?</b>
    <span>{@lessons_learned}</span>
</p>
 
<p>
    <b>What is special about FIRST or what are you looking forward to this year in FIRST?</b>
    <span>{@special_about_first}</span>
</p>

I also wrote a simple hook that runs some PHP code before each student item is saved that automatically generates the post title and page permalink (slug) based on the student’s first name and last name. It also performs some basic data validation, for example checking that the year the student joined the team is before the year the student is supposed to graduate from the team.

This went into my theme’s functions.php but in production should be placed in a custom plugin or child theme.

Additionally, I drafted a brief page in my internal documentation system that digs into the more technical details of this solution.

Implementation

This solution is 90% working out of the box, which is fantastic. However, I did notice a few shortcomings that would have to be addressed before implementation can happen.

Handing student headshots

Currently, each student has a headshot displayed on their respective student page. These headshots are stored inside the NextGen Gallery plugin on our production site. The images are included using a simple shortcode on each student page, that references each headshot’s image ID.

In order to get this working with my custom post type solution, the easy solution is to add the NextGen Gallery shortcode in my template, and then add another field asking for the student’s headshot image ID. Update: Yup, this approach does work 🙂

The students list page

The current website also has a page that displays each student’s headshot and a link to their page in a giant HTML table. This page is also manually updated which is also very tedious.

I think the solution for this is to use the Pods plugin’s built-in “archive page” functionality, which automatically generates a page that lists all instances of the custom post type (in this case, all students). The archive page itself can also be customized through a template. The hard part would be writing that template and ensuring it can handle a (theoretically) infinite number of students. Although it wouldn’t require any frequent maintenance in the near term, I would be worried about whether future website sub-team leaders would be able to figure out how to update the template if needed. I suppose this problem can be solved by writing extensive documentation though.

Migration process

As noted before, we already have hundreds of student pages created using the current method of copy-pasting a template. We would need to somehow migrate all of these pages to the new custom post type based solution, or ensure that the old and new solutions can both coexist. Migration is obviously the most “ideal” way out, but it would probably require a lot of manual work or writing a migration script. We’ll have to see about this one.

Demo

Here is a demonstration video showing how easy and simple the custom post type editing experience is.

Overall, despite some shortcomings that can be resolved with a bit of work, this looks like a very promising way to streamline my sub-team’s work. I look forward to (hopefully) implementing it soon!