Code example

In this example, we will create a very simple WordPress plugin that adds a new Person post type to WordPress. With WordPress posts we get a title which we can use for names, but there’s more to a person than a name – so we’ll create a field group to store the person’s details.

Ready? Let’s go.

Creating a plugin

Creating a plugin is well documented, but it’s easy enough that I’ll include that step here too.

Create a folder called create-person-cpt in the wp-content/plugins directory, then inside there a file called create-person-cpt.php.

Then, inside that file, name your new plugin:

That’s it! You’ve created a plugin. You can add much more here, such as a description, version, author details etc. but all that’s needed for WordPress to recognise the plugin is the name. Let’s keep going!

Registering the post type

Next up, we want our plugin to create our new post type using WordPress’ register_post_type() function.

Registering the fields

Next, Advanced Custom Fields offers a very similar method for creating and assigning field groups using their register_field_group() function.

And that’s it! With all that code in place, there should now be a new ‘person’ post type in your admin screens with custom fields for age and height.

Flawed workflow?

Something I’ve found myself wrestling with a bit recently is intelligently managing custom fields. What I’ve always done when using WordPress and Advanced Custom Fields (ACF) is create fields and field groups using the ACF management screen, generating the fields in the database, before integrating them with the frontend in my template files.

But this work process is, I’m coming to believe, a little flawed.

I’ve created entire field groups in my development environment before, only to realise I’m working with an outdated database. I could export the field group,  get the updated database, and re-import the field group, but what if I’m only editing existing field groups or fields? I’d have to delete the existing group before importing it and… well, it gets unnecessarily complicated.

And having to hold back on work until users are finished editing their site, and asking them to hold back on editing their site until the work (which may take any amount of time) is complete just interrupts everyone. That’s bad, right?

Programmatically Registering Custom Fields as a Plugin

So, when I can, what I’ve taken to doing instead is registering my custom fields in PHP-land. Creating custom post types is already commonly achieved using WordPress’ register_post_type() function. Would it not also make sense to assign custom fields to said post type in the same way?


Creating posts and custom fields this way has a couple advantages that, to me at least, make it much better as a solution to creating fields and field groups using the admin screen.Deploying code will result in new fields being there without manually interacting with the database.

Deploying code to existing websites will now result in new field groups and fields registering without the need to manually interact with the database. This brings it more inline with other systems that handle updates to the database in the codebase (for example using migrations), making things more manageable when sharing projects across developers and environments.

There’s also, in my opinion, a benefit to be gained from removing the dependency the theme has on the database. I’m of the understanding that WordPress themes should be compatible on multiple sites, and writing a theme that depends on a readily-available and easily-integrate-able plugin is much better at achieving this than writing a theme that depends on fields generated manually with no record in the codebase or means of reproducing programmatically.


While I enjoy this approach, it’s not without its side effects. Mostly, changing method for registering fields on an existing site could lead to confusion, as fields generated in the admin area won’t appear in the codebase and vice versa, which could be potentially confusing to future developers.

And, while I’ve not witnessed this personally, registering lots of fields programmatically each time WordPress is initialised could – I suspect – lead to performance degredation and slow page responses. But, I also suspect, this could be solved with page caching.