<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Brett Widmann &#8211; Chicago WordPress Developer</title>
	<atom:link href="http://brettwidmann.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://brettwidmann.com/</link>
	<description></description>
	<lastBuildDate>Mon, 25 May 2026 17:37:30 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://brettwidmann.com/wp-content/uploads/2026/05/icon-512-150x150.png</url>
	<title>Brett Widmann &#8211; Chicago WordPress Developer</title>
	<link>https://brettwidmann.com/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WordPress User Roles: The Complete Guide for Site Owners and Developers</title>
		<link>https://brettwidmann.com/wordpress-user-roles-complete-guide/</link>
					<comments>https://brettwidmann.com/wordpress-user-roles-complete-guide/#respond</comments>
		
		<dc:creator><![CDATA[Brett Widmann]]></dc:creator>
		<pubDate>Mon, 25 May 2026 17:37:30 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://brettwidmann.com/?p=1263</guid>

					<description><![CDATA[You just hired a talented freelance writer to help scale your content marketing. You want them to log into your website, draft their posts, format the text, and get everything ready for your final review. What you don’t want is for them to accidentally publish a half-finished draft, mess with your carefully configured Elementor layouts,...]]></description>
										<content:encoded><![CDATA[<p>You just hired a talented freelance writer to help scale your content marketing. You want them to log into your website, draft their posts, format the text, and get everything ready for your final review. What you <em>don’t</em> want is for them to accidentally publish a half-finished draft, mess with your carefully configured Elementor layouts, or wander into your WP Engine server settings.</p>
<p>You navigate to the WordPress dashboard, click &#8220;Add New User,&#8221; and pause. The dropdown menu presents you with a list: <em>Administrator, Editor, Author, Contributor, Subscriber.</em> What’s the actual difference? And which one is safe to assign?</p>
<p>As a WordPress consultant, I spend a lot of time auditing infrastructure and cleaning up site architectures. I can tell you firsthand that improper role assignment is one of the most common ways sites get accidentally broken or maliciously compromised. Giving a contractor &#8220;Administrator&#8221; access because it was easier than figuring out the right role is the WordPress equivalent of giving someone the master keys to your building when they only need to water the plants.</p>
<p>In this guide, we are going to break down how WordPress handles user roles, how to assign them correctly, and how to write clean, performance-minded code to create your own.</p>
<hr />
<h2>The Philosophy: Scope of Trust, Not Seniority</h2>
<p>The biggest mistake site owners make is treating WordPress roles like a corporate hierarchy. They give the CEO the &#8220;Administrator&#8221; role because it sounds like the highest rank, and they give the new hire &#8220;Subscriber.&#8221;</p>
<p>WordPress roles are not about seniority. They are about <strong>scope of trust and operational necessity</strong>.</p>
<p>This boils down to a core security concept known as the Principle of Least Privilege: a user should only have the bare minimum access rights necessary to perform their specific job.</p>
<h2>The Default WordPress Roles Demystified</h2>
<p>Out of the box, a standard WordPress installation ships with five primary user roles. Here is exactly what they can and cannot do.</p>
<h3>1. Administrator</h3>
<p>The Administrator has the keys to the kingdom.</p>
<ul>
<li><strong>Capabilities:</strong> They can do everything. Publish posts, delete pages, install or delete plugins, change the core theme, alter deep database settings, and delete other users.</li>
<li><strong>Who gets it:</strong> Only the absolute core technical owners of the site. Your lead developer, your server administrator, and perhaps the primary business owner.</li>
<li><strong>The Risk:</strong> An Administrator can install a rogue plugin, break your caching layers, or accidentally wipe your database. Hand this role out very sparingly.</li>
</ul>
<h3>2. Editor</h3>
<p>The Editor is the master of your content, but they are locked out of the site&#8217;s infrastructure.</p>
<ul>
<li><strong>Capabilities:</strong> Publish, edit, and delete any post or page on the site, regardless of who wrote it. They can moderate comments, manage categories, and upload media files.</li>
<li><strong>Who gets it:</strong> Your Content Manager, Marketing Director, or Lead Editor.</li>
</ul>
<h3>3. Author</h3>
<p>The Author is the master of their <em>own</em> domain.</p>
<ul>
<li><strong>Capabilities:</strong> Write, edit, publish, and delete their <em>own</em> posts. They can also upload files to the media library.</li>
<li><strong>Limitations:</strong> They cannot touch posts written by other people, and they cannot create or edit Pages (like your Homepage or Contact page).</li>
<li><strong>Who gets it:</strong> Trusted staff writers or regular columnists who are authorized to publish directly to the live site.</li>
</ul>
<h3>4. Contributor</h3>
<p>The Contributor is perfect for external freelancers.</p>
<ul>
<li><strong>Capabilities:</strong> They can write and edit their own posts.</li>
<li><strong>Limitations:</strong> They <strong>cannot</strong> publish their posts. A Contributor must submit their draft for review, and an Editor or Administrator must click &#8220;Publish.&#8221; Standard Contributors also cannot upload files to the Media Library.</li>
<li><strong>Who gets it:</strong> Freelance writers, guest bloggers, or new employees whose work requires editorial oversight.</li>
</ul>
<h3>5. Subscriber</h3>
<p>The Subscriber is the lowest tier of access.</p>
<ul>
<li><strong>Capabilities:</strong> Log into the site, read content, and manage their own user profile (like changing their password).</li>
<li><strong>Limitations:</strong> Everything else. They cannot write posts or see the backend dashboard beyond their profile page.</li>
<li><strong>Who gets it:</strong> Customers, clients, or newsletter subscribers.</li>
</ul>
<hr />
<h2>Under the Hood: Capabilities and Code</h2>
<p>Now let&#8217;s look at how WordPress handles this system beneath the surface.</p>
<p>A &#8220;Role&#8221; in WordPress is just a labeled bucket. The actual permissions <em>inside</em> that bucket are called <strong>Capabilities</strong>.</p>
<p>Capabilities are granular, specific permissions. Examples include:</p>
<ul>
<li><code>edit_posts</code></li>
<li><code>publish_posts</code></li>
<li><code>edit_others_posts</code></li>
<li><code>update_plugins</code></li>
<li><code>unfiltered_html</code></li>
</ul>
<p>When a user tries to click the &#8220;Update Plugin&#8221; button, WordPress doesn&#8217;t ask, <em>&#8220;Is this user an Administrator?&#8221;</em> Instead, the system asks, <em>&#8220;Does this user&#8217;s current role possess the <code>update_plugins</code> capability?&#8221;</em></p>
<h3>Where Roles Live in the Database</h3>
<p>WordPress stores these roles and capabilities in the database within the <code>wp_options</code> table, under the <code>wp_user_roles</code> option. It stores them as a <strong>serialized array</strong>—a structured string of data mapping out exactly which roles have which capabilities.</p>
<p>Because this data is saved directly in the database, it is persistent.</p>
<h2>Creating Custom Roles: The Clean Implementation</h2>
<p>The default roles rarely fit a growing business perfectly.</p>
<p>Let&#8217;s say you have a &#8220;Content Manager.&#8221; You want them to be able to edit and publish all Posts and Pages. However, you don&#8217;t want them messing with your plugin configurations, and you don&#8217;t want them managing other users.</p>
<p>We can programmatically create a custom role using the <code>add_role()</code> function. Here is a clean example of registering that exact role:</p>
<pre><code class="language-php">add_role(
    'content_manager',
    'Content Manager',
    [
        'read'                   =&gt; true,
        'edit_posts'             =&gt; true,
        'edit_others_posts'      =&gt; true,
        'publish_posts'          =&gt; true,
        'edit_pages'             =&gt; true,
        'edit_others_pages'      =&gt; true,
        'publish_pages'          =&gt; true,
        'upload_files'           =&gt; true,
        'manage_categories'      =&gt; true,
    ]
);
</code></pre>
<h3>The <code>init</code> Hook Performance Trap</h3>
<p>If you are writing custom code for this, there is a massive performance bottleneck you must avoid.</p>
<p>Because <code>add_role()</code> writes data directly to your <code>wp_options</code> table, you should never place this function loosely inside the <code>init</code> hook without a logical guard rail.</p>
<p>If you do, WordPress will execute a database write to recreate this role <em>on every single page load</em>. If your site gets 5,000 visitors a day, your server is rewriting the user roles array to the database 5,000 times a day. This causes unnecessary database bloat and slows down response times.</p>
<p><strong>The Fix:</strong> You only need to run <code>add_role()</code> once. Best practice is to place role creation inside a plugin activation hook (<code>register_activation_hook</code>) or run it once via WP-CLI.</p>
<p><em>(If you prefer a no-code approach, plugins like <strong>User Role Editor</strong> or <strong>Members</strong> provide excellent, visual UI wrappers for these same database modifications).</em></p>
<hr />
<h2>Your Practical Action Plan</h2>
<p>If you manage a team or maintain client sites, take five minutes today to run a quick permission audit.</p>
<ol>
<li>Log into your WordPress Dashboard.</li>
<li>Click on <strong>Users</strong> -&gt; <strong>All Users</strong>.</li>
<li>Look at the top filters or sort by the <strong>Role</strong> column.</li>
</ol>
<p><strong>If you see more than two or three Administrators, you have a security vulnerability.</strong> Does your graphic designer really need Admin access to upload a logo? Does the SEO agency you hired two years ago still have the keys to the server? Downgrade or delete those accounts immediately.</p>
<p>Map your company hierarchy to actual capabilities. When in doubt, ask yourself: <em>&#8220;What is the absolute minimum level of access this person needs to do their job today?&#8221;</em> Getting your WordPress user roles right creates a secure, streamlined environment. It allows your team to do their best work without the looming fear of accidentally bringing down the entire website.</p>
<hr />
<p><em>Ready to dive deeper into custom permissions? Check out the technical companion to this post: <strong><a href="https://brettwidmann.com/extending-role-capabilities-in-wordpress/">Extending Role Capabilities in WordPress</a></strong>, where we cover how to modify existing roles without rewriting the whole array.</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://brettwidmann.com/wordpress-user-roles-complete-guide/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Extending Role Capabilities in WordPress</title>
		<link>https://brettwidmann.com/extending-role-capabilities-in-wordpress/</link>
					<comments>https://brettwidmann.com/extending-role-capabilities-in-wordpress/#comments</comments>
		
		<dc:creator><![CDATA[Brett Widmann]]></dc:creator>
		<pubDate>Mon, 10 Jun 2019 03:17:26 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Permissions]]></category>
		<category><![CDATA[Roles and Capabilities]]></category>
		<guid isPermaLink="false">https://brettwidmann.com/?p=679</guid>

					<description><![CDATA[WordPress comes equipped with a standard user role management system granting permissions and actions limited to each role. In this tutorial, I provide a summary of the default roles and their capabilties in WordPress and demonstrate how to add capabilities to existing roles.]]></description>
										<content:encoded><![CDATA[<p>WordPress comes equipped with a standard user role management system granting permissions and actions limited to each role. In this tutorial, I provide a summary of the default roles and their capabilties in WordPress and demonstrate how to add capabilities (similar to permissions in other platforms) to existing roles. Each approach has caveats, which I highlight in each example.</p>
<p>First, we&#8217;ll take a look at the default roles WordPress has to offer.</p>
<p><em>Note: If you&#8217;re looking for a quick solution involving no coding/development, please download the <a href="https://wordpress.org/plugins/user-role-editor/" target="_blank" rel="noopener noreferrer">User Role Editor</a> plugin.</em></p>
<h2>Default WordPress Roles and Capabilities</h2>
<p>By default, a typical WordPress installation has five default user roles:</p>
<ol>
<li>Administrator</li>
<li>Editor</li>
<li>Author</li>
<li>Contributor</li>
<li>Subscriber</li>
</ol>
<p>To understand each role, I&#8217;ve provided a summary of each.</p>
<h3>Administrator</h3>
<p>The Administrator role is the most powerful role in the WordPress ecosystem. Administrators have the ability to:</p>
<ul>
<li>Add, edit, and delete all content types and users</li>
<li>Add, edit, and delete plugins and themes</li>
<li>Update the WordPress Core</li>
<li>Completely control the website</li>
</ul>
<p>Smaller sites usually delegate this role to the owner of the website or to a dedicated developer/webmaster who deploys regular updates and manages technical operations for the website. Anyone who does not require this level of capabilities should be assigned a different role.</p>
<h3>Editor</h3>
<p>Editors control and manage the content aspects of a WordPress website. Editors have the ability to:</p>
<ul>
<li>Add, edit, puslish, and delete all content types</li>
<li>Moderate, edit, and delete comments on posts</li>
<li>Create categories</li>
<li>Add categories</li>
<li>Create and add tags</li>
</ul>
<p>Editors do not have capabilities to change site settings or perform technical changes like updating plugins, updating themes, or adding/removing other users.</p>
<h3>Author</h3>
<p>Authors manage and produce their own content on a WordPress site. Authors have the ability to:</p>
<ul>
<li>Add, edit, publish, and delete their own posts</li>
<li>Add categories</li>
<li>Create and add tags</li>
</ul>
<p>Unlike Editors, Authors can only view comments on their posts, but they cannot moderate, approve, or delete them.</p>
<h3>Contributor</h3>
<p>Contributors create their own content on a WordPress site. Contributors have the ability to:</p>
<ul>
<li>Add and edit their own posts</li>
<li>Create and add tags</li>
</ul>
<p>Like Authors, Contributors can only view comments on their posts, but they cannot moderate, approve, or delete them.</p>
<h3>Subscriber</h3>
<p>The Subscriber role is the most restricted role. The only capabilities this role has is the ability to update their own user profile information and to change their login password. This role is useful for websites that have a subscription model where users must login to read content or leave comments.</p>
<h2>Extending Current Role Capabilities</h2>
<p>Sometimes, the base roles and capabilities aren&#8217;t enough and an existing role needs to be extended. In a recent project, I needed to give the Subscriber role the ability to read private posts and pages on a site. Instead of adding a plugin to do this, I decided to extend the roles using the <a href="https://developer.wordpress.org/reference/functions/get_role/" target="_blank" rel="noopener noreferrer">get_role()</a> and <a href="https://codex.wordpress.org/Function_Reference/add_cap" target="_blank" rel="noopener noreferrer">add_cap()</a> WordPress functions.</p>
<p>There&#8217;s a number of approaches to solving this problem, so I&#8217;ll provide two different examples with their pros and cons.</p>
<h3>Extending Roles in functions.php</h3>
<p>This is probably the quickest and simplest solution for extending capabilities on a role; a function is created that where the Subscriber role is retrieved via get_role() and stored in a variable. The role then gets the read_private_posts and read_private_pages capabilities added to it via add_cap(). Overall, this approach is pretty simple and straightforward. This approach is also the one I see floating around the internet as the defacto solution. Below is an example.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="php">// Make private posts and pages available to subscribers
function subs_read_private_content(){
    $subRole = get_role( 'subscriber' );
    $subRole-&gt;add_cap( 'read_private_posts' );
    $subRole-&gt;add_cap( 'read_private_pages' );
}
add_action( 'init', 'subs_read_private_content' );</pre>
<h4>Caveats</h4>
<ul>
<li>This method will write to the database even if the capability has been registered.</li>
<li>This method will fire on every page load, compromising performance.</li>
</ul>
<h3>Extending Roles Using a Custom Plugin</h3>
<p>A more robust and performance friendly approach to this problem requires a bit of extra work, but makes up for the performance caveats in the previous example. In this example, we&#8217;ll create a simple plugin that extends the capabilities of the Subscriber role.</p>
<p>When writing a plugin, the <a href="https://developer.wordpress.org/reference/functions/register_activation_hook/" target="_blank" rel="noopener noreferrer">register_activation_hook()</a> function is used to trigger the code when the plugin is activated, meaning it will only fire once. It must be taken into account, though, that the capabilities should be disabled/removed when the plugin is deactivated, so the <a href="https://developer.wordpress.org/reference/functions/register_deactivation_hook/" target="_blank" rel="noopener noreferrer">register_deactivation_hook()</a> needs to be used to remove the capabilities when the plugin is deactivated.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="php">&lt;?php

/**
 * Plugin Name: Allow Subscribers to Read Private Content
 * Plugin URI: https://brettwidmann.com
 * Description: A plugin that allows subscribers to read private posts and pages
 * Version: 1.0
 * Author: Brett Widmann
 * Author URI: https://brettwidmann.com
 */

register_activation_hook(__FILE__, function()
{
    // Make private posts and pages available to subscribers
    $subRole = get_role( 'subscriber' );
    $subRole-&gt;add_cap( 'read_private_posts' );
    $subRole-&gt;add_cap( 'read_private_pages' );
});

register_deactivation_hook(__FILE__, function()
{
    // Make private posts and pages unavailable to subscribers
    $subRole = get_role( 'subscriber' );
    $subRole-&gt;remove_cap( 'read_private_posts' );
    $subRole-&gt;remove_cap( 'read_private_pages' );
});</pre>
<h4>Caveats</h4>
<ul>
<li>This solution depends on activation/deactivation of the plugin</li>
<li>What happens if the plugin is live in production, but an update to the plugin is pushed?</li>
</ul>
<h2>Conclusion</h2>
<p>While WordPress has multiple approaches to solving problems, the relationship between what needs to be achieved and the database always needs to be taken into consideration, especially when writing plugins and themes.</p>
<p>Along with writing clean and effective code, please document any changes and overrides so that other developers who may inherit your site in the future can understand the how and why your changes were made (or better yet, a reminder for yourself).</p>
<p>Did I miss something? Feel free to leave a comment below or <a href="https://brettwidmann.com/contact/">contact me</a> if you have any questions.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://brettwidmann.com/extending-role-capabilities-in-wordpress/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
