This document discusses implementing a standardized WordPress solution across multiple sites at a university. It outlines common problems faced such as lack of oversight and security issues. The solution implemented a branded Genesis theme with common plugins and custom features. It addresses technical challenges around using WordPress, Genesis, and plugins at scale across a network. Custom fields, post types, and taxonomies were implemented to model content types. The summary focuses on the high-level approach and key technical challenges addressed.
5. S A M E P R O B L E M S ,
S A M E S O L U T I O N
6. W E G O T 9 9 P R O B L E M S
• No acceptable central campus solution
• No past oversight or control
• No idea what has been built independently
• Rogue servers
• Itinerant workers
7. W E G O T 9 9 P R O B L E M S
• Poor code
• No updates
• No branding
• Insecure, unprofessional sites
• Tiny staff
• 100s of migration and new site requests
8. S O L U T I O N
• One-size-fits-most WordPress template & plugin suite
• Managed WordPress hosting
• Backups
• Security monitoring
• Automatic critical updates
• Support
• Free to campus users*
9. B R A N D E D T H E M E S O L U T I O N
• Flexible
• 6 layout options
• logo toggles
• several color schemes
• Responsive
• Accessible
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23. C O M M O N E L E M E N T S
• WP Engine
• Genesis child theme
• Custom post types & taxonomies
• Advanced Custom Fields plugin
• Gravity Forms plugin
• CAS Maestro plugin
• GitHub Updater WP Pusher plugin
24. W H Y W P E N G I N E ?
• Existing campus contract
• Daily backups & one-button restore feature
• Staging copies
• Automatic security updates
• Optimized for performance
• Sucuri remediation of security incidents
25. W P E N G I N E C A V E A T S
• Price jumps after 100 installs
• Solution: Multisite
• Bandwidth / visitor limitations (vs storage)
• Restore points include entire multisite network
• Solution: Migrate DB Pro plugin
26. W H Y G E N E S I S ?
• Built-in…
• Layout options
• Color schemes
• SEO features
• plugins for slider, grid loops, multi-column text
• featured content widgets
• package of professional child themes
27. G E N E S I S C A V E A T S
• No grandchild themes
• Solution: JP Custom CSS plugin
• Obscure to new developers
• Solutions:
• Visual Hook Guide
• StudioPress snippet library
• StudioPress theme documentation
28. P S E U D O - G R A N D C H I L D T H E M E S
• Theme option: site-specific directory name
• If filled in, and if it exists…
• Enqueue style.css
• Include functions.php
29. C A S M A E S T R O C A V E A T S
• Minimal payload; no tailored onboarding
• WP login back door not visible
• No mobile app support
• or any other app relying on XML-RPC
• WP usernames must match CAS
• Character limits are not the same*
30. S I T E S E T U P W I Z A R D
I F Y O U A R E N O T U S I N G C A S , C O N S I D E R …
31. N E T W O R K - A C T I V A T E D P L U G I N S
• Advanced Custom Fields
• BE Subpages Widget
• CAS Maestro
• Display Posts Shortcode
• Enable Media Replace
• Genesis Grid
• Gravity Forms
• Image Widget
• JP Custom CSS
• JP Widget Visibility
• Menu Social Icons
• My Eyes Are Up Here
• Related Posts By Taxonomy
• Safe Redirect Manager
• Seamless Sticky Custom Post Types
• Simple Page Ordering
• Term Management Tools
• WCAG Fields for Gravity Forms
• WP Post Type Archive Links
• WP Editor Widget
• WP Help
• WP REST API
• WP REST API Custom Fields
• WP101
32. P L U G I N C A V E A T S
• Is it maintained?
• Can we maintain it?
• Should we rewrite it?
• Can we hook into it?
• Licensing
33. J E T P A C K S U B S T I T U T E S
• Users shouldn’t have to maintain wordpress.com
accounts; Jetpack disconnects every few weeks
• Developer mode doesn’t actually work very well
• JP Widget Visibility
• JP Carousel
• JP Custom CSS
34. S P E C I A L T Y P L U G I N S
• Download Monitor
• Document Revisions
• The Events Calendar Pro (Modern Tribe)
• WP LaTeX
• Visualizer
35. S E A R C H P L U G I N S
• Relevanssi Premium
• SearchWP
• Google CSE
37. F E A T U R E S
• People directories (faculty, staff, student, combined)
• Simple course catalog
• Building / equipment directory
• Publication lists
• Research project profiles
38. E D I T I N G F E A T U R E S
• Widget style chooser
• Pull quotes
• Editor toolbar changes
• Rich text footer option
• Centrally managed footer links
39. F R O N T E N D F E A T U R E S
• Branding options
• Color schemes
• Custom widgets
• Readability-style template for long documents
40. A D M I N F E A T U R E S
• Dashboard widgets
• Screen option defaults
• Edit screen columns
• Microtext changes
• Posts page warning
41. N E T W O R K A D M I N F E A T U R E S
• Logins go through main network site (CAS whitelist)
• Default network role for subsite users
• Main site login redirect for subsite users
• Sortable Sites column for upload file usage
42. C O N T E N T M O D E L
People
Subject Areas
Organizations
People Type
(Committees)
(Groups)
Courses
Subject Areas
Organizations
Publications
Subject Areas
Research
Subject Areas
Facilities
Subject Areas
Facility Type
43. C U S T O M F I E L D S &
E D I T S C R E E N S
F O R A L L F I V E C U S T O M P O S T T Y P E S
62. C O N T E N T M O D E L I N G
Q U E S T I O N S
• What things are you writing about? How are they
related? How are they grouped?
• How detailed can we get and keep the editing process
sustainable?
• Should different groups of people have permission to
edit different things?
63. C U S T O M F I E L D Q U E S T I O N S
• What are the parts that make up each thing?
• Which of those fit the fields the CMS provides, and
which do we need to create?
• What should the editing experience be for each part?
64. T A X O N O M Y Q U E S T I O N S
• Do we have any groups in which several kinds of
categories are mixed? Can these be separated into
more clearly delineated groups?
• Do our authors understand the differences between
each group?
• Should items in different groups have completely
different sets of fields? (Maybe a post type is better.)
65. F I E L D O R T A X O N O M Y ?
What is the format of this data?
Should the input be a
controlled list?
Should duplicates be
avoided? FIELDTAXONOMY
NoYes
Text Anything Else
66. A D V A N C E D
C U S T O M
F I E L D S
G E N E R A T E W P
O R
C P T U I
+
R A P I D P R O T O T Y P E S
70. D E S I G N C O N T E N T I N C O N T E X T
• Single page views
• Date-based archives
• Taxonomy-based archives
• Site search results
• Specialized search results
• Home page features
76. F I E L D T O T A X O N O M Y
W P A L L E X P O R T
77.
78.
79.
80. W P A R C H I V E S U S U A L L Y
I N C L U D E …
• Content or excerpts
• All post types in taxonomy archives
• All subcategories’ posts in parent archives
84. G E N E S I S T A B L E L O O P S
function scl_loop_table_headers( $headers ) {
$headerrow = '';
foreach ( $headers as $header ) {
$headerrow .= sprintf( "<th>%s</th>n", $header );
}
return sprintf( '<div class="loop"><table cellspacing="0" class="responsive">
<thead>
<tr>
%s
</tr>
</thead>
<tbody>'."n", $headerrow );
}
85. G E N E S I S T A B L E L O O P S
function scl_loop_table_cells( $data ) {
$datarow = '';
$rowindex = 1;
foreach ( $data as $title => $field ) {
$class = '';
if ( empty( trim ( $field ) ) )
$class = ' class="empty"';
$tag = 'td';
if ( 1 == $rowindex )
$tag = 'th';
$datarow .= sprintf( '<%s title="%s" %s>%s</%1$s>'."n", $tag, $title, $class, $field );
$rowindex++;
}
return sprintf( "<tr id='post-%d' %s>n %s n </tr>n", get_the_ID(), genesis_attr( 'entry' ),
$datarow );
}
86. G E N E S I S T A B L E L O O P S
remove_action( 'genesis_loop', 'genesis_do_loop' );
add_action( 'genesis_loop', 'scl_course_table_loop', 10 );
function scl_course_table_loop() {
if ( have_posts() ) :
$headers = array( esc_html__('Course'), esc_html__('Number'), esc_html__('Instructor(s)'), esc_html__('Time') );
echo scl_loop_table_headers( $headers );
while ( have_posts() ) : the_post();
$data = array(
sprintf( '<a href="%s" title="%s">%s</a>', esc_url( get_permalink() ), the_title_attribute( 'echo=0' ),
get_the_title() ),
get_field( 'course_number' ),
get_field( 'instructors' )
);
echo scl_loop_table_cells( array_combine( $headers, $data ) );
endwhile; //* end of one post
scl_loop_table_footer();
endif; //* end loop
}
87.
88.
89.
90. T A B L E L O O P C A V E A T S
• No settings interface
• Will override Grid Loop settings—user confusion?
93. L I S T C H I L D P A G E S
function scl_append_child_pages( $content = '' ) {
$type = get_post_type();
if ( is_post_type_hierarchical( $type ) && empty( $content ) ) {
$args = array(
'echo' => 0,
'depth' => 1,
'title_li' => '',
'child_of' => get_the_ID(),
'post_type' => $type
);
$content .= '<ul class="childpages">' . wp_list_pages( $args ) . '</ul>';
}
return $content;
}
94. L I S T C H I L D P A G E S
function scl_child_pages_shortcode() {
return scl_append_child_pages();
}
add_shortcode( 'child-pages', 'scl_child_pages_shortcode' );
add_shortcode( 'subpages', 'scl_child_pages_shortcode' );
add_filter( 'the_content', 'scl_append_child_pages' );
95. C P T A R C H I V E T E R M D I V I S I O N S
• Archives settings option
• Divide posts by selected taxonomy
• Further subdivide by child terms? (depth)
96.
97. D E E P T A X O N O M Y T E R M
A R C H I V E S
98. S H A R E D T A X O N O M Y A R C H I V E S
• Titles and breadcrumbs reflect only one term
• Post types all mixed together
• post_type not set
99. S H A R E D T A X O N O M Y T I T L E S
https://gist.github.com/sillybean/ae00bea06ff1513d48ed1fd9cbaca3eb
https://gist.github.com/sillybean/4f592e462ea51866082a099b11c6309d
100. S H A R E D T A X O N O M Y
B R E A D C R U M B S
101. F I N D _ P O S T _ T Y P E ( )
function scl_find_post_type() {
$type = get_query_var( 'post_type' );
if(( !isset( $type ) || empty( $type )) && is_tax()) {
$current_term = get_queried_object();
$tax_obj = get_taxonomy( $current_term->taxonomy );
if ( count( $tax_obj->object_type ) == 1 )
$type = $tax_obj->object_type[0];
}
return $type;
}
102. R E P L A C E L O O P W I T H P O S T T Y P E
L I S T
103. R E P L A C E L O O P W I T H P O S T T Y P E
L I S T
add_action( 'genesis_meta', 'scl_taxonomy_loop_switch' );
function scl_taxonomy_loop_switch() {
if ( function_exists( 'scl_find_post_type' ) )
$type = scl_find_post_type();
else
$type = get_query_var( 'post_type' );
if ( empty( $type ) || 'any' == $type || is_array( $type ) ) {
remove_action( 'genesis_loop', 'genesis_do_loop' );
add_action( 'genesis_loop', 'scl_list_taxonomy_post_types', 1 );
}
}
104.
105. A D D P O S T T Y P E A R G U M E N T
add_filter( 'term_link', 'tax_link_for_post_type', 10, 3 );
function tax_link_for_post_type($termlink, $term, $taxonomy){
$tax_obj = get_taxonomy( $taxonomy );
// if this is not a shared taxonomy, bail
if ( count( $tax_obj->object_type ) == 1 )
return $termlink;
$post_type = scl_find_post_type();
if ( !isset( $post_type ) || 'any' == $post_type )
return $termlink;
return add_query_arg( 'post_type', $post_type, $termlink );
}
106. P E R - P O S T - T Y P E S I D E B A R S
add_action( 'get_header', 'scl_cpt_switch_sidebar' );
function scl_cpt_switch_sidebar() {
remove_action( 'genesis_sidebar', 'genesis_do_sidebar' );
add_action( 'genesis_sidebar', 'scl_do_sidebar' );
}
107. P E R - P O S T - T Y P E S I D E B A R S *
function scl_do_sidebar() {
if ( is_home() && !is_front_page() )
$type = 'post';
else
$type = scl_find_post_type();
if ( is_active_sidebar( $type ) )
dynamic_sidebar( $type );
else
genesis_do_sidebar();
}
113. S Y N C E D F O O T E R L I N K S
add_action( 'genesis_footer', 'scl_footer_required_links' );
function scl_footer_required_links() {
if ( false === ( $links = get_transient( 'scl_footer_required_links' ) ) ) {
$response = wp_remote_get( 'http://example.com/wp-json/wp/v2/pages/2' );
if ( wp_remote_retrieve_response_code( $response ) == 200 && ! is_wp_error( $response ) ) {
$body = json_decode( wp_remote_retrieve_body( $response ), true );
$links = wp_kses_post( $body['content']['rendered'] );
}
set_transient( 'scl_footer_required_links', $links, 12 * HOUR_IN_SECONDS );
}
echo apply_filters( 'scl_footer_required_links', $links );
}
114.
115. F O O T E R T E X T C U S T O M I Z E R
F I E L D
add_action( 'customize_register', 'scl_customizer_sections' );
function scl_customizer_sections( $wp_customize ) {
$wp_customize->add_section( 'scl_footer', array(
'title' => 'Footer Text',
'priority' => 105,
'capability' => 'edit_pages',
) );
$wp_customize->add_setting( 'scl_footer_text', array(
'default' => '',
'sanitize_callback' => 'scl_sanitize_footer_text',
'transport' => 'postMessage',
) );
$wp_customize->add_control( 'scl_footer_text', array(
'label' => 'Footer text (copyright, etc.)',
'section' => 'scl_footer',
'type' => 'text',
) );
}
119. F O O T E R R I C H T E X T O P T I O N
remove_action( 'genesis_footer', 'genesis_do_footer' );
add_action( 'genesis_footer', 'scl_custom_footer' );
function scl_custom_footer() {
echo '<div class="footer-content">';
echo do_shortcode( get_field( 'footer_text', 'option' ) );
echo '</div><!-- end .footer-content -->';
}
122. U S E R S I G N U P P R O C E S S
• Site request form:
• contact info
• desired URL
• Offsite delegation
• Font licensing (&^#*@)
• Copy template blog
• Add user to blog
123. D E F A U L T N E T W O R K S I T E R O L E
function tees_default_roles( $user_id ) {
if ( is_main_site() && !is_user_member_of_blog( $user_id ) )
add_user_to_blog( get_current_blog_id(), $user_id, 'subscriber' );
}
add_action( 'wpmu_activate_user', 'tees_default_roles', 10, 1 );
add_action( 'wpmu_new_user', 'tees_default_roles', 10, 1 );
add_action( 'user_register', ‘tees_default_roles', 10, 1 );
124. C A S U S E R N A M E
R E S T R I C T I O N S
125. D A S H B O A R D W I D G E T S
• My Sites
• Way finder: CPTs and taxonomies
• Way finder: Options page content
• Link to support form
126.
127. L O G I N R E D I R E C T S : N E T W O R K
add_filter( 'login_redirect', 'tees_subsite_login_redirect', 100, 3 );
function tees_subsite_login_redirect( $redirect_to, $request_redirect_to,
$user ) {
if ( !is_user_member_of_blog( $user->ID ) ) {
// this is the main network site. Stupid name.
global $current_site;
return get_site_url( $current_site, '', 'admin' );
}
return $redirect_to;
}
128. C H A N G E T H E A D M I N U I
• Hide unneeded features
• Make everything on the screen relevant
• Change placeholders and labels
• Add toolbar options for pattern library elements
• Add inline help
• Document in the CMS
130. T U R N O F F S C R E E N O P T I O N S
<?php
add_filter( 'default_hidden_meta_boxes', 'my_default_hidden_screen_options', 10, 2
);
function my_default_hidden_screen_options( $hidden, $screen ) {
$hide_these = array(
'dashboard_primary',
'postcustom',
'trackbacksdiv',
);
return array_merge( $hidden, $hide_these );
}
131. T U R N O N S C R E E N O P T I O N S
add_filter( 'default_hidden_meta_boxes', 'scl_toggle_meta_boxes', 10, 2 );
function scl_toggle_meta_boxes( $hidden, $screen ) {
$hide_these = array( ... );
if ( $screen->base == 'nav-menus' ) {
$show_these = array(
'add-post-type-course',
'add-post-type-people',
'add-post-type-publication',
'add-post-type-facility',
'add-post-type-research',
'add-people_type',
'add-organization',
'add-subject_area',
'add-facility_type',
'add-publication_type',
);
$hidden = array_diff( $hidden, $show_these );
}
return array_merge( $hidden, $hide_these );
}
132.
133. M A K E E V E R Y T H I N G
R E L E V A N T
A D M I N C O L U M N S
134. M A K E E V E R Y T H I N G
R E L E V A N T
A D M I N C O L U M N S
135. M A K E E V E R Y T H I N G
R E L E V A N T
A D M I N C O L U M N S
137. C H A N G E P L A C E H O L D E R S
<?php
add_filter( 'enter_title_here', 'my_title_placeholders' );
function my_title_placeholders( $placeholder ){
$screen = get_current_screen();
switch ( $screen->post_type ) {
case 'people':
$placeholder = 'Enter full name';
break;
case 'course':
$placeholder = 'Enter course title';
break;
case 'facility':
$placeholder = 'Enter building name and number';
break;
default: break;
}
return $placeholder;
}
139. C H A N G E L A B E L S
F E A T U R E D I M A G E S
140. C H A N G E L A B E L S
F E A T U R E D I M A G E S
141. C H A N G E L A B E L S
<?php
remove_meta_box( 'postexcerpt', 'post', 'side' );
add_meta_box('postexcerpt', __( 'Plain Text Summary' ),
'post_excerpt_meta_box', 'post', 'normal', 'high');
148. C H A N G E I N L I N E H E L P
<?php
remove_meta_box( 'postexcerpt', 'post', 'side' );
add_meta_box( 'postexcerpt', __( 'Plain Text Summary' ), 'custom_post_excerpt_meta_box',
'post', 'normal', ‘high’ );
function custom_post_excerpt_meta_box( $post ) { ?>
<label class="screen-reader-text" for="excerpt"><?php _e( 'Plain Text Summary' ) ?></label>
<textarea rows="1" cols="40" name="excerpt" id="excerpt">
<?php echo $post->post_excerpt; // textarea_escaped ?>
</textarea>
<p><?php
__( 'The plain text summary will appear on archive pages (e.g. lists of posts by category)
and in search results.' );
?></p>
<?php
}
149. C H A N G E I N L I N E H E L P
<?php
remove_meta_box( 'postexcerpt', 'post', 'side' );
add_meta_box( 'postexcerpt', __( 'Plain Text Summary' ), 'custom_post_excerpt_meta_box',
'post', 'normal', ‘high’ );
function custom_post_excerpt_meta_box( $post ) { ?>
<label class="screen-reader-text" for="excerpt"><?php _e( 'Plain Text Summary' ) ?></label>
<textarea rows="1" cols="40" name="excerpt" id="excerpt">
<?php echo $post->post_excerpt; // textarea_escaped ?>
</textarea>
<p><?php
__( 'The plain text summary will appear on archive pages (e.g. lists of posts by category)
and in search results.' );
?></p>
<?php
}
151. P O S T S P A G E M E S S A G E
add_action( 'admin_notices', 'scl_postspage_print_notices' );
function scl_postspage_print_notices() {
$screen = get_current_screen();
if ( $screen->parent_base != 'edit' || $screen->base != 'post' || $_REQUEST['action'] != 'edit'
)
return;
$posts_page = get_option( 'page_for_posts' );
if ( !$posts_page )
return;
if ( $_REQUEST['post'] == $posts_page )
echo '<div class="error"><p>This page is a container for the most recent posts. It should
always be empty, and you should never edit this page. To add a news item, go to <a
href="post-new.php">Posts -- Add New</a>.<p></div>';
}
156. P A T T E R N L I B R A R Y I N
T O O L B A R
157. A D D T O O L B A R S T Y L E S &
B U T T O N S
A D V A N C E D T I N Y M C E
158. A D D T O O L B A R S T Y L E S &
B U T T O N S
A D V A N C E D T I N Y M C E
159. A D D T O O L B A R S T Y L E S &
B U T T O N S
A D V A N C E D T I N Y M C E
160. A D D T O O L B A R S T Y L E S &
B U T T O N S
A D V A N C E D T I N Y M C E
161. R E M O V I N G T O O L B A R B U T T O N S
function scl_mce_buttons( $buttons ) {
$remove = array( 'underline', 'alignjustify' );
return array_diff( $buttons, $remove );
}
add_filter( 'mce_buttons_2', 'scl_mce_buttons' );
162. A D D T O O L B A R S T Y L E S &
B U T T O N S
S H O R T C A K E U I
163. A D D T O O L B A R S T Y L E S &
B U T T O N S
S H O R T C A K E U I
164. A D D T O O L B A R S T Y L E S &
B U T T O N S
S H O R T C A K E U I
165. A D D T O O L B A R S T Y L E S &
B U T T O N S
S H O R T C A K E U I
169. B L O C K Q U O T E + C I T E B U T T O N
function scl_pullquote_mce_button() {
if ( 'true' == get_user_option( 'rich_editing' ) ) {
add_filter( 'mce_external_plugins', 'scl_pullquote_add_tinymce_plugin' );
add_filter( 'mce_buttons', 'scl_pullquote_register_mce_button' );
}
}
add_action('admin_head', 'scl_pullquote_mce_button');
function scl_pullquote_add_tinymce_plugin( $plugin_array ) {
$plugin_array['blockquote_cite'] = get_stylesheet_directory_uri() .'/js/mce-buttons.js';
return $plugin_array;
}
function scl_pullquote_register_mce_button( $buttons ) {
return array_push( $buttons, 'blockquote_cite' );
}
180. M O R E C O N T E N T S T R A T E G Y
S T U F F
• More code
• A content inventory plugin
• Videos
• A book
• http://stephanieleary.com/tag/content-strategy/
181. I M P O R T A N Y T H I N G T O
W O R D P R E S S
Y E T A N O T H E R P R E S E N T A T I O N
Hinweis der Redaktion
The lack of mobile app support actually doesn’t bother me much, because custom post types and fields aren’t available through the mobile app, either. That makes it not very useful for managing sites that use CPTs and fields heavily. The web admin interface is responsive and generally works pretty well on mobile devices, and includes all the WP admin screens.
We look for plugins that are maintained by a company or have a strong user base. Plugins that haven’t been updated in over two years get a thorough evaluation: have they not been updated because WP functionality hasn’t changed? Can we maintain it if we have to?
These are plugins that we make available to site admins, but do not activate by default.
In WordPress, this indicates that you need a custom field. There’s no easy way to sort posts by taxonomy term the way you can in Drupal.
Of course, in Drupal you can create new post types and taxonomies in the admin UI. In WordPress, those features are deliberately hidden. You can generate the code for your own plugin (my preference), or use the CPT UI plugin.
Advanced Custom Fields is probably the easiest and most popular way to add fields to WordPress posts. Create a field group, choose which post types it applies to, and start adding fields.
For each new field, you can add inline instructions, placeholder text, and a default value that will be returned if the field is left blank.
Contexts: home page widgets, single view, date archives, taxonomy archives, post type archives, search results
SKIP TO #85 IF IT’S BREAK TIME
You can change direction pretty easily even after you’ve migrated a lot of content into WordPress.
Term Management Tools gives you new bulk actions on your category/tag/term screens. The Merge tool is great for cleaning up duplicates and typos, and for consolidating terms if you find that you got too granular.
You can also move terms from one taxonomy to another with this plugin. Choose “change taxonomy” from the bulk actions dropdown.
Once we have the file downloaded, we switch to WP All Import.
Once we have the file downloaded, we switch to WP All Import.
BREAK
In these projects, I’m one step removed from end user experience. I’m just trying to make the CMS not suck so that people can use it. Departments’ communications staff will work with them on specific content goals.
I work with a lot of higher ed institutions and government agencies, which have more than their fair share of people for whom web content is an “other duty as assigned.” They probably update the site once or twice a semester—and if they can’t remember or figure out how to do it, they simply won’t. Their other tasks are higher priorities for the institution, so they aren’t punished for this, and the site devolves into obsolescence.
https://github.com/joraff/wp-plugin-username-restriction-override
and
https://github.com/joraff/tamuwpcas
https://gist.github.com/sillybean/46ac65a5498dcd6f6643df93d1314d8b
or
https://gist.github.com/sillybean/85979b0a355171a6f023cbea0172f444
Eileen Webb calls this “Training the CMS,” and she has a great article about it at A List Apart.
The array here is made up of the IDs of the boxes you want to hide. Just inspect your screen to figure out what to enter.
http://stephanieleary.com/2016/06/wordpress-hidden-gem-screen-option-defaults-filter/ and http://stephanieleary.com/2016/06/wordpress-closed-meta-boxes-filter/
This is the default edit list screen for a custom Publications post type. Editors of this site don’t really care who posted the publication or when it was originally posted. But all we can do in screen options is turn things off.
We can add new columns using the Admin Columns plugin. Here, we really want to know whether the publication was funded by a particular grant, which publisher it came from, and when the entry was last modified.
Voila.
Well, that’s super confusing. Should it be their name or their job title?
WordPress has a filter called enter_title_here that lets you change the placeholder text in the post title field. More: http://stephanieleary.com/2016/06/wordpress-hidden-gem-enter_title_here-filter/ (Note that I haven’t localized these labels in order to keep the code simple for the slide.)
Last year, WP added some new labels for featured images, and you can now change that phrase to something that makes more sense for your content: portrait, product image, building photo, etc. https://make.wordpress.org/core/2015/12/11/additional-labels-for-custom-post-types-and-custom-taxonomies/
Last year, WP added some new labels for featured images, and you can now change that phrase to something that makes more sense for your content: portrait, product image, building photo, etc. https://make.wordpress.org/core/2015/12/11/additional-labels-for-custom-post-types-and-custom-taxonomies/
As long as you keep the ID (the first argument) and the name of the callback function (the third argument) the same, you can change the title (the second argument) to whatever you want. https://bryce.se/2012/10/14/change-title-of-wordpress-meta-boxes/
I’m not wild about the built-in excerpt field instructions. To change it, we can adapt the code we used before to change its title.
This time, we’re replacing not only the title but the callback function that displays the form field. As long as we leave the textarea field alone, we’re not doing anything that changes the way the excerpt works. The text is up for grabs. Here, I’ve changed both the field label, which is used only for screen readers, and the instructions. https://gist.github.com/sillybean/e96db15f0d8049a02cfc3af7c2d11f6e
This time, we’re replacing not only the title but the callback function that displays the form field. As long as we leave the textarea field alone, we’re not doing anything that changes the way the excerpt works. The text is up for grabs. Here, I’ve changed both the field label, which is used only for screen readers, and the instructions. https://gist.github.com/sillybean/e96db15f0d8049a02cfc3af7c2d11f6e
Now that we have control of this text, we can move it around, too. If you want it to appear above the textarea to be more consistent with your other inline help, just move the paragraph above the form field.
https://gist.github.com/sillybean/2515588
This is the Advanced TinyMCE plugin. It lets you build all kinds of new things into the toolbar.
This option is really powerful. If you’ve created an editor stylesheet that mimics your front end styles, you can load its classes into the TinyMCE formats menu. You might have to tweak things a little—it doesn’t do well with multiple classes on a single element—but this is a fast way to put your pattern library into the toolbar.
On this site, there were only two things from the pattern library that we didn’t just build in to default styles for things like tables and lists. First, we wanted to offer the option for button-style links. That went into the Formats dropdown. Second, we wanted to add a more advanced blockquote that could include a linked citation. For that, I built a new TinyMCE button. https://www.gavick.com/blog/wordpress-tinymce-custom-buttons is a very thorough tutorial on doing this in WordPress.
You can also add more complicated patterns using shortcodes, and, for a better user experience with those, the Shortcake UI plugin.
It drives me a little crazy that their demo is for a pull quote, because — QED — I think that’s better handled by normal markup and a toolbar button.
It does give you a really nice interface for adding the new content.
But you have to go through the Add Media button to access it, which my users have found very unintuitive… so much so that we replaced this with toolbar buttons. I like Shortcake UI in theory, but in practice I’ve never needed to use it in production because I’ve tried hard to find ways around using shortcodes at all.
https://gist.github.com/sillybean/68d53b9b729804737e9d9774bc1d0a60
and
https://gist.github.com/sillybean/f1e034e121a8276929d250fcfa773d3c
I’ve seen a lot of organizations with beautiful documentation on how to use the CMS… stored as a Word document in a shared network drive, or in a helpdesk’s knowledgebase, or virtually anywhere but INSIDE THE CMS. Meet users where they are. This is the WP Help plugin. For those of you in another CMS, all this does is create a post type that’s hidden from the public, with its own toolbar link.
What do the content editors think of the prototype? What do they not understand? Start making a list.