Designing a museum collection WordPress site

This year I am pleased to be involved with helping a small museum get established with an online presence.  It is run by a team of dedicated volunteers who have a fairly large number of items which need to be catalogued. We decided at the outset that any system we designed should be compliant with the industry standards and so I have based the solution on Spectrum 5.0, which is the UK collection management standard produced by The Collections Trust.

Spectrum has 9 primary procedures which outline the minimum requirements needed to meet the standards.  These are more to do with ensuring that correct procedures are followed than with the software. However a good software system can facilitate the process and this is the basis of the project.

The following pages explain how to build a dedicated collection management system using WordPress.

Create a new site with the appropriate plugins

The intention is that the collection site itself is not a publicly available website. The collections database should only be accessed by the curators of the museum and its purpose is primarily as a database for the collection and to manage movement and storage of the objects.

A separate public site which is managed as a normal website can draw data from the collection by means of an API.  This will be explained further in a later post.


Get a url for the collection. The collection can be on a separate domain or as a sub domain of your current site.  For the purposes of this article I will assume you have installed the new WordPress site in a directory called ‘collection’  which is directly under the root of the main site. Eg.

Essential plugins

We will need to add custom post types, taxonomies and new user roles to the system.  This can be done by creating some custom code but for convenience  we will use a couple of plugins.

User roles – User Role Editor

Custom Post Types – CustomPress

Configure the plugins

1. User Role Editor

From the Users menu item, select User Role Editor

From this screen select ‘Add role’ and enter the following in the pop-up screen

The curator role is now added but it doesn’t have permissions to do anything.  We will add these in the next step.

2. CustomPress

We use this plugin to create the custom post types.

These are – object, location, movable_unit, location_history, object_image, acquisition

Choose CustomPress –> Content Types  from the menu.

Click the ‘Post Types’ Tab

Click the ‘Add Post Type’ button

The next screen allows you to enter all the parameters necessary to create a custom post type.

Follow the project WordPress for Collections to find out more.


Saving revisions for custom post type meta data

I was recently asked to create a membership listing site and although there are may great plugins for this, none offered the specific functionality needed.

The solution had to be to create a custom post type with custom fields. My favourite plugin to do this is CustomPress by WPMUDEV. Apart from the convenience of using a plugin to create the CPT, a key requirement of the project was that the client needed to create additional fields herself. The plugin provides an excellent easy to use interface for this.

Another key requirement was that there would be different users who could update the records of the members and the system admin would need to be able to keep track of the changes made by the other users.

WordPress by default does not keep revisions of post meta data so I set about devising a solution. Searching online I came across an excellent post by John Blackbourn with many helpful pointers. So here is my solution for revisions of custom fields of a custom post type.

Create the CPT and fields

Using CustomPress I created a ‘member’ post type and assigned a number of custom fields to it.  The first task is to create a function to retrieve those fields.

function ca_members_fields(){  global $CustomPress_Core;   $member_fields=$CustomPress_Core->get_custom_fields_set('member');   return $member_fields; }

Add the custom fields to the revisions screen

By default WordPress makes only the main post fields available in the revisions screen.
So we need to add our meta data fields to the revision screen array.

add_filter( '_wp_post_revision_fields','ca_member_fields', 10, 1 );

function ca_member_fields( $fields ) {
   foreach($members_fields as $fieldname=>$members_field){ 
     $fields['ct_'.$fieldname] = $members_field['field_title']; 
 return $fields;

CustomPress stores the key for a metadata field prefixed with ‘ct_’  so notice in the code that the field name is prefixed as such.

To show the revision data on the screen we need to create a function to get the meta data for each field.

function ca_field( $value, $field_name,$post ) { 
   foreach($members_fields as $fieldname=>$members_field){ 
     $value= get_metadata( 'post',$post->ID, 'ct_'.$fieldname , true ); 
  return $value; 

Each of the custom fields needs to be added to the revision screen. So we add the filter _wp_post_revision_field_{customfield} to each of these custom fields. Then hook this into the admin_head filter so that it gets run on page load.

function ca_custom_admin_head() {
  foreach($members_fields as $fieldname=>$members_field){ 
   add_filter( '_wp_post_revision_field_'.'ct_'.$fieldname, 'ca_field', 10, 4 ); 
add_action( 'admin_head', 'ca_custom_admin_head' );

Saving revisions

Tell WordPress to save the revision data for each of the custom fields

add_action( 'save_post','ca_save_member_revision', 10, 2 );
function ca_save_member_revision( $post_id, $post ) {
   if ( $parent_id = wp_is_post_revision( $post_id ) ) {
    $parent = get_post( $parent_id );
                foreach($members_fields as $fieldname=>$members_field){      
                    $meta = get_post_meta( $parent->ID, 'ct_'.$fieldname, true );
                    if ( false !== $meta ){
                         add_metadata( 'post', $post_id, 'ct_'.$fieldname, $meta );   

Finally allow each of the custom fields to be restored.

add_action( 'wp_restore_post_revision',    'ca_restore_revision', 10, 2 );
function ca_restore_revision( $post_id, $revision_id ) {
    $post     = get_post( $post_id );
    $revision = get_post( $revision_id );        
        foreach($members_fields as $fieldname=>$members_field){         
           $meta = get_metadata( 'post', $revision->ID, 'ct_'.$fieldname, true );
           if ( false !== $meta ){    
            update_post_meta( $post_id, 'ct_'.$fieldname, $meta );