Menu Search
Jump to the content X X
SmashingConf London Avatar

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. our upcoming SmashingConf London, dedicated to all things web performance.

How To Make WordPress Hard For Clients To Mess Up

WordPress is a wonderfully powerful CMS that ships with many versatile features giving it the flexibility to work out of the box for a wide range of users. However, if you are a professional building custom themes and plugins, sometimes these features can be problematic. The same features and options that allow off-the-shelf themes to adapt to many different use cases can sometimes also be used to undermine a carefully designed custom theme built for a specific use case.

The following article comprises a collection of code snippets that I use again and again on almost every WordPress project. What they all have in common is that they limit functionality that is either unnecessary, confusing, or unsafe. Everything that follows can be used on any site, but these tips are especially applicable for professionals making custom themes and plugins for clients.

Further Reading on SmashingMag: Link

The notable distinction is that custom themes can be built to serve a specific purpose. So the blanks for the authors’ content can and should also be much narrower. A well-designed WordPress theme should make as many design decisions as possible so the author doesn’t have to.

Disable The Plugins And Theme Editor Link

There is no good reason why anyone should be live-editing your custom theme or plugin files via the WordPress dashboard. Professionals don’t work that way, and muggles5 typically don’t realize just how easy it is to break a site by skipping a single semicolon. It is also a security vulnerability hackers can exploit. Fortunately, our friends at made it really easy to disable this feature. Simply add the following snippet to the wp-config.php file.

define( 'DISALLOW_FILE_EDIT', true );

In addition to the theme editor, this will also disable the plugin editor. I consider this a feature not a bug.

Wordpress plugins editor6
WordPress plugins editor. (View large version7)

Limit The Visual And Text Editor Link

By default, the WordPress WYSIWYG editor supports far too many formatting options for a well-designed custom theme. Letting clients override text colors or font sizes is a fast way to make even the most chic site look cheap and ugly. If blog post text is designed to always be left-aligned, why give the author a button to right-align it? Do you think it will look good if the text on the About page is purple, bold, and italicized? Then don’t arm your client with the means to do it. In most situations I recommend disabling the visual editor entirely.

Ugly typography page8
Ugly typography page. (View large version9)

Disabling The Visual Editor Link

Add the following snippet to your theme’s functions.php file and the tab to toggle the WYSIWYG editor will disappear.

function emersonthis_disable_visual_editor(){
    # add logic here if you want to permit it selectively
    return false;
add_filter('user_can_richedit' , 'emersonthis_disable_visual_editor', 50);

This is a good start, but you’ll notice that the bold and italic buttons are still present on the plain text editor. In my experience, clients abuse these buttons much less often when the instant gratification of the WYSIWYG editor is gone. But I still prefer to remove them if they are not necessary.

The visual editor tab10
The visual editor tab. (View large version11)

Removing Bold And Italic Quicktags From The Text Editor Link

The text editor has quicktag buttons that will wrap selected text with <strong> and <em> tags. Add the following code in your theme’s functions.php file and authors will no longer have bold or italics buttons.

# Removes bold and italic quicktags from text editor
function emersothis_quicktags_settings( $qtInit  ) {
    //To disable ALL butons it must be set to "," (not "")
    $qtInit['buttons'] = 'more,';
    return $qtInit;
add_filter('quicktags_settings', 'emersonthis_quicktags_settings');

This removes the possibility that your client will decide to, say, italicize an entire article. But this does not remove the ability to write markup into the text editor by hand. Every now and then that can come in handy when you’re in a pinch.

If you are in a rare situation where the user should be formatting text themselves, you can leave the visual editor enabled but disable specific buttons individually.

Disabling Buttons On The Visual Editor Link

One of the few times I leave the visual editor enabled is when authors are writing long posts or pages that have internal structure of their own. For example, an author of a 10-page article might need the ability to add subheadings. In these situations I set up custom classes for the subsections and then disable all the other formatting buttons that are not needed.

The WordPress API for modifying the TinyMCE12 editor is a bit tricky because you need to look up the code names used to refer to each button you want to remove. You get the most bang for your buck by removing the “kitchen sink” button which toggles the entire second row that contains the most problematic formatting buttons. Adding the following code to your theme’s functions.php file will do this.

# Remove visual editor buttons
function emersonthis_tinymce_buttons($buttons)
    # Remove the text color selector
    $remove = array('wp_adv'); //Add other button names to this array
    # Find the array key and then unset
    return array_diff($buttons,$remove);

One trick to figuring out the code name of the button you want to remove is by inspecting the markup of the form. At the time of writing, each button has a class name that begins with mce-i- followed by the code name you would put in the array above.

Remove The “Add Media” Button Link

The “Add media” button appears by default whenever a custom post type supports the editor feature. But custom post types can be used for a wide range of things, and often it is inappropriate for that field to include images.

Blog post filled with ugly images13
Blog post filled with ugly images. (View large version14)

Most of the time, when I expect the author to publish an image to accompany text, I use post thumbnails (aka featured images). This makes it easy to integrate the images into theme templates, and it also gives the developer more control over the size and specifications for the images.

Ad hoc photos embedded using the “Add media” button in the editor are hard to control and they have a tendency to look awkward depending on where the author inserts the image in relation to the surrounding text. They also cause confusion for many authors, because at a glance the “Add media” button is easily confused with the “Featured image” upload button that appears further down the page (by default), and may be used very differently by the theme. I almost always remove it, by adding the following code to the theme’s functions.php file.

# Remove media buttons
function emersonthis_remove_add_media(){
    # do this conditionally if you want to be more selective
    remove_action( 'media_buttons', 'media_buttons' );
add_action('admin_head', 'emersonthis_remove_add_media');

You can add logic before the remove_action() to remove only the media button conditionally for certain post types. For example, you might want to let authors add images to pages, but not blog posts which instead use thumbnails.

Disable Theme Customizer Options Link

If you are working on a child theme, the parent theme may offer customization options that are inappropriate for the child. The customization options may be unused in your child theme, or have the potential to break things. Either way, the WordPress theme customizer API15 makes it easy to get rid of them by adding the following snippet to your theme’s functions.php file.

# Remove customizer options.
function emersonthis_remove_customizer_options( $wp_customize ) {
    // $wp_customize->remove_section( 'static_front_page' );
    // $wp_customize->remove_section( 'title_tagline' );
    $wp_customize->remove_section( 'colors' );
    $wp_customize->remove_section( 'header_image' );
    $wp_customize->remove_section( 'background_image' );
    // $wp_customize->remove_section( 'nav' );
    // $wp_customize->remove_section( 'themes' );
    // $wp_customize->remove_section( 'featured_content' );
    // $wp_customize->remove_panel( 'widgets' );
add_action( 'customize_register',

Each line in the snippet above corresponds to an individual theme customization option that you can disable by uncommenting it.

Hide Unused Dashboard Menu Items Link

Not every site has the same types of content; some sites have no blog, for example. If we apply the same logic to the WordPress dashboard that we apply to any other user interface, it is confusing and unnecessary to show buttons that do not do anything. In this example, the Posts menu item would be unnecessary, so let’s remove it by adding the following snippet to functions.php:

function emersonthis_custom_menu_page_removing() {
  // remove_menu_page( 'index.php' );                  //Dashboard
  // remove_menu_page( 'jetpack' );                    //Jetpack* 
  remove_menu_page( 'edit.php' );                   //Posts
  remove_menu_page( 'upload.php' );                 //Media
  // remove_menu_page( 'edit.php?post_type=page' );    //Pages
  remove_menu_page( 'edit-comments.php' );          //Comments
  // remove_menu_page( 'themes.php' );                 //Appearance
  // remove_menu_page( 'plugins.php' );                //Plugins
  // remove_menu_page( 'users.php' );                  //Users
  // remove_menu_page( 'tools.php' );                  //Tools
  // remove_menu_page( 'options-general.php' );        //Settings
add_action( 'admin_menu', 'emersonthis_custom_menu_page_removing' );

Each line corresponds to a specific menu in the dashboard. The file names do not always match the name that appears in the dashboard menu, so the commented lines are left in as a quick reference.

The Posts menu appears by default whether or not the site has a blog16
The Posts menu item appears by default whether or not the site has a blog. (View large version17)

The WordPress dashboard without the Posts menu item. (View large version19)

It is important to understand that removing these menu items does not actually revoke the user’s permissions. A user could still access the hidden menu item directly using the URL. If the goal is to make the dashboard less cluttered by hiding superfluous controls, then this is probably fine. If the goal is to actually prevent a user from accessing those controls, then you will need to modify the capabilities of the user’s role20. To accomplish this, add a snippet like the following to the activation hook of a plugin (it only needs to run once):

global $wp_roles; // global class
$role = 'author';
$cap = 'delete_published_posts';
$wp_roles->remove_cap( $role, $cap );

Use this comprehensive table of all capabilities21 to find the specific capabilities you can add or remove for each of the default roles.

Add A Hint About How Line Breaks Work In The Editor Link

By default the visual editor (TinyMCE) will create a new paragraph when the author presses Return. If you just want an old fashioned line break (aka carriage return) you need to press Shift+Return. This is nifty and powerful but not intuitive for many authors. I’ve started adding a quick reminder to avoid the inevitable complaint about “a bunch of weird white space” showing up in a post or page.

Blog post with ugly extra white space22
Blog post with ugly extra white space. (View large version23)

Add the following snippet to your functions.php file. Change the value of $tip to say whatever you want to remind your authors of.

# Adds instruction text after the post title input
function emersonthis_edit_form_after_title() {
    $tip = '<strong>TIP:</strong> To create a single line break use SHIFT+RETURN. By default, RETURN creates a new paragraph.';
    echo '<p style="margin-bottom:0;">'.$tip.'</p>';

This technique could be used to inject a reminder about anything you want authors to remember when adding or editing content.

Posts page with whitespace tip added24
Posts page with white space tip added. (View large version25)

Do Not Dole Out Administrator Accounts Link

The WordPress administrator role is very powerful and with great power comes great responsibility26. Some clients are experienced WordPress power users who administer their site competently. Many of them are not. The latter should not be poking around as administrators. Instead, make them an editor and create a separate admin account with a super strong password. If you have an ongoing affiliation with the client you can hang on to those credentials until the client is ready to administer the site themselves.

Users list full of admins27
Users list full of admins. (View large version28)

Alternatively, give the client both sets of credentials and have them store the admin credentials somewhere safe and only use it to perform admin tasks. Many clients will promptly lose the admin credentials but that is fine: the password can always be reset, and these are often the types of clients who will rehire you to do the routine site maintenance for them anyway.

The most important reason for being stingy with admin accounts is that they are a security vulnerability. A pleasant side effect is that beginner WordPress users often find the dashboard UI less overwhelming when they log in as authors or editors because there are fewer menus to sort through while learning basic skills such as adding or editing posts.

Use mu-Plugins Link

The mu-plugins/ directory has existed for a long time, but most WordPress hackers I meet have never heard of it. The “mu” stands for must use. The directory is an alternative location where plugins can be installed.

Must use plugins interface in WordPress dashboard29
Must use plugins interface in WordPress dashboard. (View large version30)

The difference is that “must use” plugins are automatically active and cannot be disabled by accident throughout the dashboard. They are also loaded before the other plugins. This is ideal for plugins that must be present for the site to run properly. It’s also a great alternative for non-presentational hacks that might normally get jammed into your custom theme’s functions.php file. For example, I like to define custom post types in a mu-plugin, because that content should persist whether or not a particular theme is active.

The mu-plugins/ directory does not exist out of the box. You create it manually inside wp-content/.


The biggest limitation is that WordPress only looks for files in the top level of mu-plugins/ and will ignore code inside a subdirectory. However, you can work around this by creating a single PHP file at the top of mu-plugins/ that loads code from a sibling subdirectory. Also keep in mind that update notifications do not apply to mu-plugins. I think of mu-plugins/ as the place to put important code that the client should never have to think about.

Read more about must use plugins31 in the Codex. If you want to require other plugins by preventing the ability to deactivate them, you might find the WDS-Required-Plugins32 library useful.

Final Note Link

You may find it counterintuitive to disable functionality that WordPress gives you for free. But remember that your client is not paying you to give them a lot of buttons. Your job is to make an effective, robust website that is tailored to match the client’s goals. By disabling problematic or extraneous functionality you are actually delivering more value.

If you want more snippets, I have created a public GitHub repository of useful WordPress snippets33 which contains up-to-date versions of the hacks above, as well as others I add periodically. If you have your own handy snippets you want to share, pull requests are more than welcome!

(dp, ml, og)

Footnotes Link

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19 //
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33

↑ Back to top Tweet itShare on Facebook

Emerson is a designer, developer, and problem solver. He has been working on the web since 2006. He is currently the CTO of TransitScreen.

  1. 1

    Great stuff. Could you share some example about how to hide unused dashboard menu items depends on user role?

    • 2

      Florian Schrödl

      July 7, 2016 11:58 am

      If you want to hide menus for everyone except the admins:

      if ( !current_user_can( 'manage_options' ) ) {
      add_action( 'admin_menu', 'hide_not_needed_menus_from_admin_panel'], 20 );

      function hide_not_needed_menus_from_admin_panel() {
      remove_menu_page( 'edit.php' );

  2. 3

    Thank you for your article, very interesting and useful!

    After delivering a website I always have to update themes, cms and plugins because they require upgrades for the website to be safe. At first I started disabling updates but this now does not make a wordpress less vulnerable.

    When you talk about “Disable The Plugins And Theme Editor” and don’t do updates anymore (neither the client of course) does this make websites less secure?


    • 4

      Tim Wakeling

      July 7, 2016 11:03 am

      Disabling the editor doesn’t mean you can’t update plugins; they are different. :) Plugin updates aren’t affected by removing the Web browser editor using this code. Disabling the editor just means your users can’t go in and fiddle with the plugins’ source code from within your browser. You can still edit them in the usual way using your code editor of choice and FTP, which is much safer (although editing third party plugins is not recommended of course). Does that clear up the confusion?

    • 5

      As Tim said, updating 3rd party plugins is not a risk and should not be disabled. But preventing the client(s) from tinkering with the source code manually through the UI is a risk and should.

  3. 6

    Great tip. But I don’t see much value by removing bold and italic button on the plain text editor.

  4. 8

    Tim Wakeling

    July 7, 2016 11:12 am

    These are all good tips and I use most of them myself — except I happen to prefer to edit the toolbar of the editor rather than disable the visual side of it entirely. The visual editor does a lot of very handy things like show YouTube embeds and images, which my clients appreciate (though on some post types it may indeed be appropriate to stop them inserting images in the content, so that’s a useful tip for some situations too).

    I use a bit of code like below to simplify the toolbar rather than remove it, reducing it to one line and giving the client things I trust them with — bold, italic, alignment, heading/paragraph selector and preset CSS styles like button link (for which obviously the theme has to provide in its CSS), and even tables actually — while removing the more troublesome ones like “Paste from Word” and things that are hard to understand in my experience. My code also forces pasted text to come in plain, which foregoes the nicety for developers like me of having links etc come in with it, but for clients it’s much easier to strip it all back and tell them they have to add any styles they want back in after pasting. Results in cleaner pages. :)

    function tw_simple_visual_editor( $initArray ) {
    $style_formats = array(
    // Each array child is a format with its own settings
    'title' => 'Button link',
    'classes' => 'button',
    'selector' => 'a'
    'title' => 'Link with doc icon',
    'classes' => 'document-link',
    'selector' => 'a'
    $initArray[ 'style_formats' ] = json_encode( $style_formats );
    $initArray[ 'block_formats' ] = 'Heading 2=h2;Heading 3=h3;Heading 4=h4;Paragraph=p';
    $initArray[ 'toolbar1' ] = 'bold italic strikethrough | formatselect styleselect | alignleft aligncenter alignright | bullist numlist indent outdent | blockquote hr table | link unlink | undo redo'; // you can easily add/remove buttons by editing this row, as you feel appropriate
    $initArray[ 'toolbar2' ] = '';
    $initArray[ 'paste_text_use_dialog' ] = 'false';
    $initArray[ 'paste_auto_cleanup_on_paste' ] = 'true';
    $initArray[ 'paste_remove_styles' ] = 'true';
    $initArray[ 'paste_as_text' ] = 'true';
    $initArray[ 'paste_text_sticky' ] = 'true';
    return $initArray;
    add_filter( 'tiny_mce_before_init', 'tw_simple_visual_editor' );

  5. 10

    The WordPress plugin Adminimize is your friend here, you can customise menu options so content authors will never see plugins for example, so no need to disable.

    • 11

      Exactly. That’s the one I’ve been using for quite some time now :)
      The internal anchor points of the interface are a bit perplexing, at least at the start.

      cu, w0lf.

    • 12

      I use the same plugin (adminimize), it should have simpler controls but works great and it’s really versatile.

  6. 13

    Benjamin Denis

    July 7, 2016 3:07 pm

    this is exactly why I create a plugin to do this in a much powerful way, called “WP Admin UI”.
    You can download it on

  7. 14

    Matthew Trow

    July 7, 2016 8:23 pm

    For me, a mu plugin is be “Tinymce Advanced” :

    It allows a great deal of control over tinymce.

    Another mu plugin, “members”, which allows granular control over user roles:

  8. 15

    Andy Leverenz

    July 11, 2016 3:01 pm

    Awesome share. A lot of stuff I have overlooked before that I knew was possbile but didn’t know how to perform. Thanks!

  9. 16

    Marcelo Ferro

    July 12, 2016 7:24 am

    Thanks for sharing these tips, even though yo agregaria ones lines of code
    to have a layer more than safety,
    * change wp-admin url
    * not used user admin and generic pass, generate secure passwords as
    * protect the htaccess wp-config.php file.
    * use wordfence and for security and also spam (wpbruiser).

  10. 17

    Giorgos Sarigiannidis

    July 12, 2016 4:21 pm

    I had the exact same thoughts as you regarding limiting access to clients. I chose a rather different approach, though, which was more role-centered. More specifically, I, as the administrator, can see everything, with no restrictions. I never give administrator access to client’s, though, as I prefer making them Editors. If a client asks for administrator access, I create a separate account and I advice him/her to use it only when there is an actual reason. Most of the times, though, they won’t even ask for it.

    Then, to limit access even more, I packed all the necessary functions in a plugin (Slash Admin: ). The areas that I focus are those:

    – Hide unnecessary options from the Admin menu for non admins (so editors won’t get overwhelmed with options that have no meaning for the current website).
    – Disable tags and categories when not in use.
    – Hide specific pages from non admins. For example, you might not want your editors to have access to the static frontpage, the blog page or pages that you use as page templates.
    – Allow editors to manage Menus and Widgets and access some other appearance settings previously acessible only to admins (for example, you might want to give your client the option to modify the website’s menu, but you would rather avoid making him/her an administrator).
    – Hide notices about updating WordPress and other plugins for all users except from Admins (sometimes clients get confused with those notices and think that there is something wrong with the website).

    Besides that, though, there are some more things that you can take care to make an admin panel more user-friendly, such as:
    – customize the login screen
    – hide the – sometimes confusing – dashboard widgets (this can be done from WordPress itself) and create a helper widget with my contact details (again, for this I use Slash Admin).
    – hide unnecessary columns from the backend’s post lists (e.g. hide the categories’ or comments’ column if you don’t use them), as well as unnecessary features from the post edit screen (for example, don’t show an excerpt field if you don’t use it on your frontend). Again, this can be done from WordPress itself with no plugins or custom code needed).

  11. 18

    Lee Chapoton

    July 13, 2016 4:43 pm

    Great article! I’m about to set off on building my first theme from scratch for a volunteer organization and this is invaluable advice. I’m actually quite surprised it is the first time I can recall hearing of doing this even though I’ve read and watched several online tutorials.

    The particular organization I am helping needs to adhere to their own brand guidelines and removing the ability for authors to make their own “creative” decisions (i.e. Ooh, this Comic Sans makes a wonderful heading!) is a huge headache saver. Otherwise, I foresee lots of situations similar to your “Ugly typography page” and “Blog post filled with ugly images” taking place.

    I totally agree with your comment “By disabling problematic or extraneous functionality you are actually delivering more value.” As designers and developers we should be focused on providing a quality product that users can easily add content to without breaking the look or feel of the original design.


  12. 19

    Good article. I am a web developer for 6 years long. At the start I created my own plugin to customize the wordpress dashboard for every customers. But I now a lot of premium plugins released for simplifying the wordpress dashboard. Personally I recommend wpshapere plugin which makes life easier
    Thanks for the developer.

  13. 20

    Zaybar Vasquez

    July 29, 2016 3:11 am

    Hi Emerson,

    Great article for WordPress developers who create websites for clients.

    I recently discovered a great plugin which covers some of your hack tips and more called Disable Blogging. I think is worth checking out. I found it really convenient that it packs all of the features I need to help simplify the WordPress dashboard for my clients and disable all blog and functionality.

  14. 21

    Great article for WordPress developers, i hope you can help
    me also whit this :
    If i go to my site i can not go to the menu in dashbord i get error 505. ( so can not change structure of the menu or pages )

    Can someone help me please… ? thanks


↑ Back to top