Top 15 Ways to Secure Your WordPress Install

Wordpress Security

As the digital world starts taking over more of the real world; security or digital security to be more specific, is becoming more and more important. Then there’s WordPress; and WordPress is becoming more and more popular (currently 19% of the web). Even web applications are starting to be built on top of it.

Private information and even credit cards are flying around. So, obviously security is really important. There are a lot of steps to take to make sure our WordPress installs are secure.

Keep Everything Up To Date

Number one is kind of the obvious stuff. Keep everything up to date. Keep your WordPress install up to date. Keep all your plugins up to date.

As time progresses hackers figure out ways to breach the current software, while simultaneously the developers (most of them at least) are working to keep their code up to date with the latest standards. A lot of hacked sites are due to old out of date plugins or WordPress installs.

Don’t Use “admin” as a Username

Then, the next thing would be your admin login. You’d be surprised how much you can access from your admin login. You can access any of your theme files. PHP can be injected in there; they could take down your whole site just by having that login. So, you’ll want your user name not to be admin, which is the default. You want to change your user name to something more specific to you.

Strong Password

Also, the password needs to be a strong password, which today is upper case and lower case letters, with a sprinkle of various symbols and numbers as well. If you have one without a symbol and then you add a symbol, it’s adding that much more complexity; and is that much harder for a hacker to hack into that.

Hacking a password

Same thing goes for your database password, and user name, and your database name. Those should all be pretty encrypted as well.

Don’t Use Same Username & Password for Multiple Sites

I know a lot of this is common sense but so is eating healthy. So, moving along, you don’t want to use the same user name and password for any of your other sites. There is software such as 1Password and others that allow you to have and keep multiple passwords for multiple sites.

You can have a different login, a different user name, or even the same user name that is unique to yourself; and different very strong encrypted passwords that are unique to each and every site that this software can store for you, so you don’t have to remember and copy, and paste each and every one. You can just hit a button and it’ll automatically log you in.

This will not only help your WordPress site, but every site you have a username & login to; Your bank; Your email. Etc.

So that’s the “simple” stuff. On to some more “technical” stuff.

Protecting Against Directory Browsing

One step you may want to take is to make sure there is an empty index.php or index.html file in every folder that doesn’t have an index file. This is usually the case by default in WordPress, but doesn’t hurt to check. What this does is make it impossible to browse the folders directly, something that some web hosts support.

You could do the same thing by disabling directory browsing globally by adding the following code to your .htaccess file.

# Disable directory browsing
Options All –Indexes

SSL for Admin Interfaces

You can also force SSL on your admin interfaces within WordPress. This will make it a lot harder for potential bad guys to hack in. Although SSL won’t work without support from your host so you might want to contact them regarding this if your not sure. Some hosts may include this while others might charge for it.

It’s pretty easy to force SSL in your admin. Just add this code snippet to your wp-config.php file in your root WordPress directory.

define(‘FORCE_SSL_ADMIN’, true); 

Secure FTP

To add security when you are accessing your site via FTP, you might want to consider using SFTP instead, which is the same except the S stands for Secure. Again some hosts have this automatically, others you may need to contact to enable.

File Permissions

There are different file permissions and folder permissions that WordPress requires in order for it to run properly and to be able to properly access things through your admin dashboard, such as uploading images and files. Making sure that these files & folders have the appropriate permissions will go a long way.

So the files should be owned and writable by the user account and set to 644. Folder permissions should be set to 755. wp-config.php should be separately set to 600 (source). This will give you the maximum available protection, while also keeping everything that needs to be accessible, accessible. And of course, ask your host if you are unsure about these things. For more information you can visit here.

Change the Database Prefix

Just like changing your username from admin, we need to change the database prefixes from wp_. This is default for many WordPress installs including the convenient one-click WordPress install provided by many hosts. If you don’t change the database prefix, the table names of your site’s database are easily known to the person who is trying to hack your site.

In order to accomplish this you can follow the steps in this tutorial here or you can use a plugin like Change DB Prefix or similar.

Protect wp-config.php

*Update* Moving it outside of the root offers more protection but is only possible in root installs.

As we know now, our wp-config.php file contains all of the confidential details about our site. So it’s pretty important to protect this at all costs. An easy way to do this is by adding the following code to your .htaccess file.

<Files wp-config.php>
    order allow,deny  
    deny from all  
</Files>

Protect .htaccess

We can now protect our wp-config.php file, but what about our .htaccess file? Don’t worry, we can use the same .htaccess file to protect itself from being preyed upon. You just need to place below code in your .htaccess file.

<Files .htaccess>
    order allow,deny  
    deny from all  
</Files>

Hide Your WordPress Version

*Update* Hiding your WordPress version from the meta generator in the head doesn’t make sense as nowadays most properly coded themes add the WP version to styles and scripts.

Removing the generator meta which supplies which WordPress version you are running is important in protecting potential hackers. If you have enable the WordPress version then hackers will know when your version is out of date, and can attack accordingly. If you can absolutely not update your versoin of WordPress, this may be a good failsafe to at least hide the fact that your not running the most current version.

To hide your version of WordPress place this in the functions.php file of your current theme.

remove_action('wp_head', 'wp_generator');

Also remove it from RSS feeds using this:

function wpt_remove_version() {  
    return '';  
}  
add_filter('the_generator', 'wpt_remove_version');

Authentication Unique Keys and Salts

Authentication Unique Keys and Salts are located in your wp-config.php file and should already be there, but its good to double-check this. They are located below you database username & password requirements. Actually when you manually install WordPress on a server, you also need to manually add this. Within the commented out section is a link that will auto-generate a unique set of keys that you need to copy and paste back into the wp-config.php file.

Limit The Number of Failed Login Attempts

Limiting the number of failed login attempts could protect your site against anyone trying to guess your password or a bot trying to brute force its way in. The plugin that provides this functionality is Limit Login Attempts.

Regular Backups

If you’re not already keeping regular backups, you should be. This will not only give you peace of mind, but is almost like restoring Windows to a point in time before you downloaded that virus if you catch my drift.

Backups will not only help you recover if a hacker does succeed in accessing your site, but there are a plethora of other things that can go wrong. Its just a smart thing to do, especially if your running a business.

Some free plugins to help you keep regular backups are:
BackUpWordPress
WordPress Backup to Dropbox

Conclusion

I think that’s it. I hope I don’t have to reassure you need to start taking security more seriously. If you’re not convinced here are some interesting yet scary statistics:

  • 600,000 Facebook accounts are hacked each day (that’s about 7 accounts per second)
  • 100% of the top 100 paid apps on Android have been hacked.
  • 3 in 4 Americans have fallen or will fall victim to cyber crime due to being hacked.
  • 3 in 4 people use the same password for multiple accounts. Source

Put those last two together and I think we are on to something here…

You kind of have the idea by now. It’s just really important to be as secure as possible especially as the technology continues to develop even faster than most people can keep up with. The amount of security holes are probably growing as fast as the technology, so the amount of effort that we need to put into security would probably be growing over time as well.

Footer Menu in WordPress with CSS & HTML

Footer Menu in Wordpress

Learn how to create a footer menu within WordPress not using widgets but with CSS & HTML within the theme files.

A lot of times when creating a custom WordPress theme not all aspects of the theme need to be accessible from the WordPress dashboard. One being simple footer navigation that may never change. If it does change its not a big deal to change, but setting it up initially using widgets is kind of overkill in my opinion for just a few simple links and some copyright information.

With just some simple CSS & HTML we were able to create a decent looking menu in the matter of a minutes.

Follow me through the video and if you have any questions please leave them in the comments.

Optimizing “WordPress SEO” Plugin Settings

Optimize Wordpress SEO Settings

WordPress SEO has quickly become the #1 SEO plugin for WordPress serving millions of happy bloggers including myself. I decided to make a video about WordPress SEO because when you first activate the plugin there are actually a lot of additional things that can and should be done in order to get the most out of it. Enjoy!

A couple of useful links relating to WordPress SEO are as follows:

WordPress SEO – The Definitive Guide
WordPress Plugins by Yoast

De-Blogging Your WordPress Theme

Wordpress Blog

WordPress is technically a blogging platorm but we know today that it can be used for so much more. One popular usage of WordPress is as a CMS or even just a static site (with the benefit of having easily editable content). One step that people often forget about when transitioning WordPress over to a CMS or static site is to remove the un-needed blogging functionality out such as comments, trackbacks, pagination, etc. This will not only make your WordPress install leaner and faster (which I might add is a huge benefit) it also makes your code easier to read for future updates and maintenance.
De-Blogging WordPress

WordPress › Twenty Twelve

Twenty Twelve Theme
There are so many themes out there but I’m going to use the Twenty Twelve theme as an example to show you which code can be removed without disrupting or breaking your code if your using WordPress strictly as a CMS. That means you have no need of comments (even for an alternate use such as reviews / collaboration / suggestions), trackbacks, author profiles, pagination, etc.

twentytwelve

This is the file directory for the Twenty Twelve theme. Right off the bat we can condense this and remove some of these files to make our directory easier to navigate. But before we touch these files please understand that technically you can run WordPress off of just 2 files, the index.php and style.css. Everything else is extra and of course makes the theme that much better.The author.php file is not needed if you don’t have any need for author profiles. You can also remove the comments.php, image.php (if your not interested in having individually styled pages for your image uploads). At this point you need to consider how you are going to organize your site. Are you going to use Categories? Tags? Custom post types? Post formats? Depending on how you want to utilize WordPress as a CMS determines whether or not you can also remove one or both of the category.php & tag.php files.

So far we haven’t really enchanced the speed or made WordPress leaner from a performance standpoint but we certainly made it easier to navigate the theme directory which will probably save us time in the future filtering through files. Also note that this is a default WordPress theme and you may have another theme with many different files some of which you may need and some that you may not need. A good rule is don’t delete anything unless you know what it is!

page.php

Now lets dive into one of the files, the first being page.php. One thing we can do is remove the comments up top.

<?php
/**
 * The template for displaying all pages.
 *
 * This is the template that displays all pages by default.
 * Please note that this is the WordPress construct of pages
 * and that other 'pages' on your WordPress site will use a
 * different template.
 *
 * @package WordPress
 * @subpackage Twenty_Twelve
 * @since Twenty Twelve 1.0
 */

get_header(); ?>

	<div id="primary" class="site-content">
		<div id="content" role="main">

			<?php while ( have_posts() ) : the_post(); ?>
				<?php get_template_part( 'content', 'page' ); ?>
				<?php comments_template( '', true ); ?>
			<?php endwhile; // end of the loop. ?>

		</div><!-- #content -->
	</div><!-- #primary -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>

Next you can remove the comments_template php tag and the rest of the html comments.

<?php get_header(); ?>

	<div id="primary" class="site-content">
		<div id="content" role="main">

			<?php while ( have_posts() ) : the_post(); ?>
				<?php get_template_part( 'content', 'page' ); ?>
			<?php endwhile;?>

		</div>
	</div>

<?php get_sidebar(); ?>
<?php get_footer(); ?>

Already we are removing unecessary code that is improving our bottom line when it comes to performance. If you notice here that this .php file is retreiving another .php file where it says get_template_part. Lets open up that page which is the file named content-page.php.

content-page.php

<?php
/**
 * The template used for displaying page content in page.php
 *
 * @package WordPress
 * @subpackage Twenty_Twelve
 * @since Twenty Twelve 1.0
 */
?>

	<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
		<header class="entry-header">
			<h1 class="entry-title"><?php the_title(); ?></h1>
		</header>

		<div class="entry-content">
			<?php the_content(); ?>
			<?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'twentytwelve' ), 'after' => '</div>' ) ); ?>
		</div><!-- .entry-content -->
		<footer class="entry-meta">
			<?php edit_post_link( __( 'Edit', 'twentytwelve' ), '<span class="edit-link">', '</span>' ); ?>
		</footer><!-- .entry-meta -->
	</article><!-- #post -->

There are a few things we can remove here as well. The php tag that begins with wp_link_pages, the comments at the top, and the bottom, and also the php tag edit_post_link. We can remove the edit post link becuase of the admin bar that appears when you are logged into WordPress. If you prefer to have the link on the page you can keep it but you can remove it as well if you never use that link to edit the pages. Personally I either use the admin bar at the top which has a conveninent “Edit Page” button or I just navigate to it in the WordPress dashboard.

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
	<header class="entry-header">
		<h1 class="entry-title"><?php the_title(); ?></h1>
	</header>

	<div class="entry-content">
		<?php the_content(); ?>
	</div>
	<footer class="entry-meta">

	</footer>
</article>

So our finished code in the content-page.php file looks like this. You can even remove the footer element as well if you want since its not being used, or you can add something else within it such as social media buttons, etc. On to single.php.

single.php

<?php
/**
 * The Template for displaying all single posts.
 *
 * @package WordPress
 * @subpackage Twenty_Twelve
 * @since Twenty Twelve 1.0
 */

get_header(); ?>

	<div id="primary" class="site-content">
		<div id="content" role="main">

			<?php while ( have_posts() ) : the_post(); ?>

				<?php get_template_part( 'content', get_post_format() ); ?>

				<nav class="nav-single">
					<h3 class="assistive-text"><?php _e( 'Post navigation', 'twentytwelve' ); ?></h3>
					<span class="nav-previous"><?php previous_post_link( '%link', '<span class="meta-nav">' . _x( '←', 'Previous post link', 'twentytwelve' ) . '</span> %title' ); ?></span>
					<span class="nav-next"><?php next_post_link( '%link', '%title <span class="meta-nav">' . _x( '→', 'Next post link', 'twentytwelve' ) . '</span>' ); ?></span>
				</nav><!-- .nav-single -->

				<?php comments_template( '', true ); ?>

			<?php endwhile; // end of the loop. ?>

		</div><!-- #content -->
	</div><!-- #primary -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>

This is the single.php which displays the content for posts. Lets clean it up. Just note that there are some things you wish to keep such as previous and next posts, which is fine! I’m just trying to give you the leanest version possible.

Here is the single.php after the clean up! Big difference.

<?php get_header(); ?>

	<div id="primary" class="site-content">
		<div id="content" role="main">

			<?php while ( have_posts() ) : the_post(); ?>

				<?php get_template_part( 'content', get_post_format() ); ?>

			<?php endwhile; ?>

		</div>
	</div>

<?php get_sidebar(); ?>
<?php get_footer(); ?>

The next step would be to remove the unnecessary code from all of the post format .php files (if you choose to use them). The one file I will go through is content.php since its a big file with a lot of code in it (comparitively).

content.php

<?php
/**
 * The default template for displaying content. Used for both single and index/archive/search.
 *
 * @package WordPress
 * @subpackage Twenty_Twelve
 * @since Twenty Twelve 1.0
 */
?>

	<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
		<?php if ( is_sticky() && is_home() && ! is_paged() ) : ?>
		<div class="featured-post">
			<?php _e( 'Featured post', 'twentytwelve' ); ?>
		</div>
		<?php endif; ?>
		<header class="entry-header">
			<?php the_post_thumbnail(); ?>
			<?php if ( is_single() ) : ?>
			<h1 class="entry-title"><?php the_title(); ?></h1>
			<?php else : ?>
			<h1 class="entry-title">
				<a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'twentytwelve' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a>
			</h1>
			<?php endif; // is_single() ?>
			<?php if ( comments_open() ) : ?>
				<div class="comments-link">
					<?php comments_popup_link( '<span class="leave-reply">' . __( 'Leave a reply', 'twentytwelve' ) . '</span>', __( '1 Reply', 'twentytwelve' ), __( '% Replies', 'twentytwelve' ) ); ?>
				</div><!-- .comments-link -->
			<?php endif; // comments_open() ?>
		</header><!-- .entry-header -->

		<?php if ( is_search() ) : // Only display Excerpts for Search ?>
		<div class="entry-summary">
			<?php the_excerpt(); ?>
		</div><!-- .entry-summary -->
		<?php else : ?>
		<div class="entry-content">
			<?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'twentytwelve' ) ); ?>
			<?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'twentytwelve' ), 'after' => '</div>' ) ); ?>
		</div><!-- .entry-content -->
		<?php endif; ?>

		<footer class="entry-meta">
			<?php twentytwelve_entry_meta(); ?>
			<?php edit_post_link( __( 'Edit', 'twentytwelve' ), '<span class="edit-link">', '</span>' ); ?>
			<?php if ( is_singular() && get_the_author_meta( 'description' ) && is_multi_author() ) : // If a user has filled out their description and this is a multi-author blog, show a bio on their entries. ?>
				<div class="author-info">
					<div class="author-avatar">
						<?php echo get_avatar( get_the_author_meta( 'user_email' ), apply_filters( 'twentytwelve_author_bio_avatar_size', 68 ) ); ?>
					</div><!-- .author-avatar -->
					<div class="author-description">
						<h2><?php printf( __( 'About %s', 'twentytwelve' ), get_the_author() ); ?></h2>
						<p><?php the_author_meta( 'description' ); ?></p>
						<div class="author-link">
							<a href="<?php echo esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ); ?>" rel="author">
								<?php printf( __( 'View all posts by %s <span class="meta-nav">→</span>', 'twentytwelve' ), get_the_author() ); ?>
							</a>
						</div><!-- .author-link	-->
					</div><!-- .author-description -->
				</div><!-- .author-info -->
			<?php endif; ?>
		</footer><!-- .entry-meta -->
	</article><!-- #post -->

So lets go to work. If you aren’t going to use sticky posts you can remove lines 12-16. No comments? Remove lines 26-30. Is your site going to utilize the built in search bar? If not you can remove lines 33-37 & line 42. Don’t need the post meta (date & author of post)? Remove line 45. Do you want the edit link? If not remove line 46. And if you don’t use or need author meta remove lines 47-62. Also don’t forget to remove all the comments.

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

		<header class="entry-header">
			<?php the_post_thumbnail(); ?>
			<h1 class="entry-title"><?php the_title(); ?></h1>			
		</header>

		<div class="entry-content">
			<?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'twentytwelve' ) ); ?>
			<?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'twentytwelve' ), 'after' => '</div>' ) ); ?>
		</div>

	</article>

There are a few other minor things I removed but this is the finished product. From 65 lines of code to 14 lines of code and will function the same. We just removed all the unecessary blog functionality.

Next up is functions.php.

functions.php

Now more then ever tread with caution. Functions.php is not just something you can mess around with. Be very careful and if you don’t know what your doing it might be better to just skip over this part. With that being said, lets see the full functions.php that is included with the twentytwelve theme.

<?php
/**
 * Twenty Twelve functions and definitions.
 *
 * Sets up the theme and provides some helper functions, which are used
 * in the theme as custom template tags. Others are attached to action and
 * filter hooks in WordPress to change core functionality.
 *
 * When using a child theme (see http://codex.wordpress.org/Theme_Development and
 * http://codex.wordpress.org/Child_Themes), you can override certain functions
 * (those wrapped in a function_exists() call) by defining them first in your child theme's
 * functions.php file. The child theme's functions.php file is included before the parent
 * theme's file, so the child theme functions would be used.
 *
 * Functions that are not pluggable (not wrapped in function_exists()) are instead attached
 * to a filter or action hook.
 *
 * For more information on hooks, actions, and filters, see http://codex.wordpress.org/Plugin_API.
 *
 * @package WordPress
 * @subpackage Twenty_Twelve
 * @since Twenty Twelve 1.0
 */

/**
 * Sets up the content width value based on the theme's design and stylesheet.
 */
if ( ! isset( $content_width ) )
	$content_width = 625;

/**
 * Sets up theme defaults and registers the various WordPress features that
 * Twenty Twelve supports.
 *
 * @uses load_theme_textdomain() For translation/localization support.
 * @uses add_editor_style() To add a Visual Editor stylesheet.
 * @uses add_theme_support() To add support for post thumbnails, automatic feed links,
 * 	custom background, and post formats.
 * @uses register_nav_menu() To add support for navigation menus.
 * @uses set_post_thumbnail_size() To set a custom post thumbnail size.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_setup() {
	/*
	 * Makes Twenty Twelve available for translation.
	 *
	 * Translations can be added to the /languages/ directory.
	 * If you're building a theme based on Twenty Twelve, use a find and replace
	 * to change 'twentytwelve' to the name of your theme in all the template files.
	 */
	load_theme_textdomain( 'twentytwelve', get_template_directory() . '/languages' );

	// This theme styles the visual editor with editor-style.css to match the theme style.
	add_editor_style();

	// Adds RSS feed links to <head> for posts and comments.
	add_theme_support( 'automatic-feed-links' );

	// This theme supports a variety of post formats.
	add_theme_support( 'post-formats', array( 'aside', 'image', 'link', 'quote', 'status' ) );

	// This theme uses wp_nav_menu() in one location.
	register_nav_menu( 'primary', __( 'Primary Menu', 'twentytwelve' ) );

	/*
	 * This theme supports custom background color and image, and here
	 * we also set up the default background color.
	 */
	add_theme_support( 'custom-background', array(
		'default-color' => 'e6e6e6',
	) );

	// This theme uses a custom image size for featured images, displayed on "standard" posts.
	add_theme_support( 'post-thumbnails' );
	set_post_thumbnail_size( 624, 9999 ); // Unlimited height, soft crop
}
add_action( 'after_setup_theme', 'twentytwelve_setup' );

/**
 * Adds support for a custom header image.
 */
require( get_template_directory() . '/inc/custom-header.php' );

/**
 * Enqueues scripts and styles for front-end.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_scripts_styles() {
	global $wp_styles;

	/*
	 * Adds JavaScript to pages with the comment form to support
	 * sites with threaded comments (when in use).
	 */
	if ( is_singular() && comments_open() && get_option( 'thread_comments' ) )
		wp_enqueue_script( 'comment-reply' );

	/*
	 * Adds JavaScript for handling the navigation menu hide-and-show behavior.
	 */
	wp_enqueue_script( 'twentytwelve-navigation', get_template_directory_uri() . '/js/navigation.js', array(), '1.0', true );

	/*
	 * Loads our special font CSS file.
	 *
	 * The use of Open Sans by default is localized. For languages that use
	 * characters not supported by the font, the font can be disabled.
	 *
	 * To disable in a child theme, use wp_dequeue_style()
	 * function mytheme_dequeue_fonts() {
	 *     wp_dequeue_style( 'twentytwelve-fonts' );
	 * }
	 * add_action( 'wp_enqueue_scripts', 'mytheme_dequeue_fonts', 11 );
	 */

	/* translators: If there are characters in your language that are not supported
	   by Open Sans, translate this to 'off'. Do not translate into your own language. */
	if ( 'off' !== _x( 'on', 'Open Sans font: on or off', 'twentytwelve' ) ) {
		$subsets = 'latin,latin-ext';

		/* translators: To add an additional Open Sans character subset specific to your language, translate
		   this to 'greek', 'cyrillic' or 'vietnamese'. Do not translate into your own language. */
		$subset = _x( 'no-subset', 'Open Sans font: add new subset (greek, cyrillic, vietnamese)', 'twentytwelve' );

		if ( 'cyrillic' == $subset )
			$subsets .= ',cyrillic,cyrillic-ext';
		elseif ( 'greek' == $subset )
			$subsets .= ',greek,greek-ext';
		elseif ( 'vietnamese' == $subset )
			$subsets .= ',vietnamese';

		$protocol = is_ssl() ? 'https' : 'http';
		$query_args = array(
			'family' => 'Open+Sans:400italic,700italic,400,700',
			'subset' => $subsets,
		);
		wp_enqueue_style( 'twentytwelve-fonts', add_query_arg( $query_args, "$protocol://fonts.googleapis.com/css" ), array(), null );
	}

	/*
	 * Loads our main stylesheet.
	 */
	wp_enqueue_style( 'twentytwelve-style', get_stylesheet_uri() );

	/*
	 * Loads the Internet Explorer specific stylesheet.
	 */
	wp_enqueue_style( 'twentytwelve-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentytwelve-style' ), '20121010' );
	$wp_styles->add_data( 'twentytwelve-ie', 'conditional', 'lt IE 9' );
}
add_action( 'wp_enqueue_scripts', 'twentytwelve_scripts_styles' );

/**
 * Creates a nicely formatted and more specific title element text
 * for output in head of document, based on current view.
 *
 * @since Twenty Twelve 1.0
 *
 * @param string $title Default title text for current view.
 * @param string $sep Optional separator.
 * @return string Filtered title.
 */
function twentytwelve_wp_title( $title, $sep ) {
	global $paged, $page;

	if ( is_feed() )
		return $title;

	// Add the site name.
	$title .= get_bloginfo( 'name' );

	// Add the site description for the home/front page.
	$site_description = get_bloginfo( 'description', 'display' );
	if ( $site_description && ( is_home() || is_front_page() ) )
		$title = "$title $sep $site_description";

	// Add a page number if necessary.
	if ( $paged >= 2 || $page >= 2 )
		$title = "$title $sep " . sprintf( __( 'Page %s', 'twentytwelve' ), max( $paged, $page ) );

	return $title;
}
add_filter( 'wp_title', 'twentytwelve_wp_title', 10, 2 );

/**
 * Makes our wp_nav_menu() fallback -- wp_page_menu() -- show a home link.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_page_menu_args( $args ) {
	if ( ! isset( $args['show_home'] ) )
		$args['show_home'] = true;
	return $args;
}
add_filter( 'wp_page_menu_args', 'twentytwelve_page_menu_args' );

/**
 * Registers our main widget area and the front page widget areas.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_widgets_init() {
	register_sidebar( array(
		'name' => __( 'Main Sidebar', 'twentytwelve' ),
		'id' => 'sidebar-1',
		'description' => __( 'Appears on posts and pages except the optional Front Page template, which has its own widgets', 'twentytwelve' ),
		'before_widget' => '<aside id="%1$s" class="widget %2$s">',
		'after_widget' => '</aside>',
		'before_title' => '<h3 class="widget-title">',
		'after_title' => '</h3>',
	) );

	register_sidebar( array(
		'name' => __( 'First Front Page Widget Area', 'twentytwelve' ),
		'id' => 'sidebar-2',
		'description' => __( 'Appears when using the optional Front Page template with a page set as Static Front Page', 'twentytwelve' ),
		'before_widget' => '<aside id="%1$s" class="widget %2$s">',
		'after_widget' => '</aside>',
		'before_title' => '<h3 class="widget-title">',
		'after_title' => '</h3>',
	) );

	register_sidebar( array(
		'name' => __( 'Second Front Page Widget Area', 'twentytwelve' ),
		'id' => 'sidebar-3',
		'description' => __( 'Appears when using the optional Front Page template with a page set as Static Front Page', 'twentytwelve' ),
		'before_widget' => '<aside id="%1$s" class="widget %2$s">',
		'after_widget' => '</aside>',
		'before_title' => '<h3 class="widget-title">',
		'after_title' => '</h3>',
	) );
}
add_action( 'widgets_init', 'twentytwelve_widgets_init' );

if ( ! function_exists( 'twentytwelve_content_nav' ) ) :
/**
 * Displays navigation to next/previous pages when applicable.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_content_nav( $html_id ) {
	global $wp_query;

	$html_id = esc_attr( $html_id );

	if ( $wp_query->max_num_pages > 1 ) : ?>
		<nav id="<?php echo $html_id; ?>" class="navigation" role="navigation">
			<h3 class="assistive-text"><?php _e( 'Post navigation', 'twentytwelve' ); ?></h3>
			<div class="nav-previous alignleft"><?php next_posts_link( __( '<span class="meta-nav">←</span> Older posts', 'twentytwelve' ) ); ?></div>
			<div class="nav-next alignright"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">→</span>', 'twentytwelve' ) ); ?></div>
		</nav><!-- #<?php echo $html_id; ?> .navigation -->
	<?php endif;
}
endif;

if ( ! function_exists( 'twentytwelve_comment' ) ) :
/**
 * Template for comments and pingbacks.
 *
 * To override this walker in a child theme without modifying the comments template
 * simply create your own twentytwelve_comment(), and that function will be used instead.
 *
 * Used as a callback by wp_list_comments() for displaying the comments.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_comment( $comment, $args, $depth ) {
	$GLOBALS['comment'] = $comment;
	switch ( $comment->comment_type ) :
		case 'pingback' :
		case 'trackback' :
		// Display trackbacks differently than normal comments.
	?>
	<li <?php comment_class(); ?> id="comment-<?php comment_ID(); ?>">
		<p><?php _e( 'Pingback:', 'twentytwelve' ); ?> <?php comment_author_link(); ?> <?php edit_comment_link( __( '(Edit)', 'twentytwelve' ), '<span class="edit-link">', '</span>' ); ?></p>
	<?php
			break;
		default :
		// Proceed with normal comments.
		global $post;
	?>
	<li <?php comment_class(); ?> id="li-comment-<?php comment_ID(); ?>">
		<article id="comment-<?php comment_ID(); ?>" class="comment">
			<header class="comment-meta comment-author vcard">
				<?php
					echo get_avatar( $comment, 44 );
					printf( '<cite class="fn">%1$s %2$s</cite>',
						get_comment_author_link(),
						// If current post author is also comment author, make it known visually.
						( $comment->user_id === $post->post_author ) ? '<span> ' . __( 'Post author', 'twentytwelve' ) . '</span>' : ''
					);
					printf( '<a href="%1$s"><time datetime="%2$s">%3$s</time></a>',
						esc_url( get_comment_link( $comment->comment_ID ) ),
						get_comment_time( 'c' ),
						/* translators: 1: date, 2: time */
						sprintf( __( '%1$s at %2$s', 'twentytwelve' ), get_comment_date(), get_comment_time() )
					);
				?>
			</header><!-- .comment-meta -->

			<?php if ( '0' == $comment->comment_approved ) : ?>
				<p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.', 'twentytwelve' ); ?></p>
			<?php endif; ?>

			<section class="comment-content comment">
				<?php comment_text(); ?>
				<?php edit_comment_link( __( 'Edit', 'twentytwelve' ), '<p class="edit-link">', '</p>' ); ?>
			</section><!-- .comment-content -->

			<div class="reply">
				<?php comment_reply_link( array_merge( $args, array( 'reply_text' => __( 'Reply', 'twentytwelve' ), 'after' => ' <span>↓</span>', 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?>
			</div><!-- .reply -->
		</article><!-- #comment-## -->
	<?php
		break;
	endswitch; // end comment_type check
}
endif;

if ( ! function_exists( 'twentytwelve_entry_meta' ) ) :
/**
 * Prints HTML with meta information for current post: categories, tags, permalink, author, and date.
 *
 * Create your own twentytwelve_entry_meta() to override in a child theme.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_entry_meta() {
	// Translators: used between list items, there is a space after the comma.
	$categories_list = get_the_category_list( __( ', ', 'twentytwelve' ) );

	// Translators: used between list items, there is a space after the comma.
	$tag_list = get_the_tag_list( '', __( ', ', 'twentytwelve' ) );

	$date = sprintf( '<a href="%1$s" title="%2$s" rel="bookmark"><time class="entry-date" datetime="%3$s">%4$s</time></a>',
		esc_url( get_permalink() ),
		esc_attr( get_the_time() ),
		esc_attr( get_the_date( 'c' ) ),
		esc_html( get_the_date() )
	);

	$author = sprintf( '<span class="author vcard"><a class="url fn n" href="%1$s" title="%2$s" rel="author">%3$s</a></span>',
		esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
		esc_attr( sprintf( __( 'View all posts by %s', 'twentytwelve' ), get_the_author() ) ),
		get_the_author()
	);

	// Translators: 1 is category, 2 is tag, 3 is the date and 4 is the author's name.
	if ( $tag_list ) {
		$utility_text = __( 'This entry was posted in %1$s and tagged %2$s on %3$s<span class="by-author"> by %4$s</span>.', 'twentytwelve' );
	} elseif ( $categories_list ) {
		$utility_text = __( 'This entry was posted in %1$s on %3$s<span class="by-author"> by %4$s</span>.', 'twentytwelve' );
	} else {
		$utility_text = __( 'This entry was posted on %3$s<span class="by-author"> by %4$s</span>.', 'twentytwelve' );
	}

	printf(
		$utility_text,
		$categories_list,
		$tag_list,
		$date,
		$author
	);
}
endif;

/**
 * Extends the default WordPress body class to denote:
 * 1. Using a full-width layout, when no active widgets in the sidebar
 *    or full-width template.
 * 2. Front Page template: thumbnail in use and number of sidebars for
 *    widget areas.
 * 3. White or empty background color to change the layout and spacing.
 * 4. Custom fonts enabled.
 * 5. Single or multiple authors.
 *
 * @since Twenty Twelve 1.0
 *
 * @param array Existing class values.
 * @return array Filtered class values.
 */
function twentytwelve_body_class( $classes ) {
	$background_color = get_background_color();

	if ( ! is_active_sidebar( 'sidebar-1' ) || is_page_template( 'page-templates/full-width.php' ) )
		$classes[] = 'full-width';

	if ( is_page_template( 'page-templates/front-page.php' ) ) {
		$classes[] = 'template-front-page';
		if ( has_post_thumbnail() )
			$classes[] = 'has-post-thumbnail';
		if ( is_active_sidebar( 'sidebar-2' ) && is_active_sidebar( 'sidebar-3' ) )
			$classes[] = 'two-sidebars';
	}

	if ( empty( $background_color ) )
		$classes[] = 'custom-background-empty';
	elseif ( in_array( $background_color, array( 'fff', 'ffffff' ) ) )
		$classes[] = 'custom-background-white';

	// Enable custom font class only if the font CSS is queued to load.
	if ( wp_style_is( 'twentytwelve-fonts', 'queue' ) )
		$classes[] = 'custom-font-enabled';

	if ( ! is_multi_author() )
		$classes[] = 'single-author';

	return $classes;
}
add_filter( 'body_class', 'twentytwelve_body_class' );

/**
 * Adjusts content_width value for full-width and single image attachment
 * templates, and when there are no active widgets in the sidebar.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_content_width() {
	if ( is_page_template( 'page-templates/full-width.php' ) || is_attachment() || ! is_active_sidebar( 'sidebar-1' ) ) {
		global $content_width;
		$content_width = 960;
	}
}
add_action( 'template_redirect', 'twentytwelve_content_width' );

/**
 * Add postMessage support for site title and description for the Theme Customizer.
 *
 * @since Twenty Twelve 1.0
 *
 * @param WP_Customize_Manager $wp_customize Theme Customizer object.
 * @return void
 */
function twentytwelve_customize_register( $wp_customize ) {
	$wp_customize->get_setting( 'blogname' )->transport = 'postMessage';
	$wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage';
}
add_action( 'customize_register', 'twentytwelve_customize_register' );

/**
 * Binds JS handlers to make Theme Customizer preview reload changes asynchronously.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_customize_preview_js() {
	wp_enqueue_script( 'twentytwelve-customizer', get_template_directory_uri() . '/js/theme-customizer.js', array( 'customize-preview' ), '20120827', true );
}
add_action( 'customize_preview_init', 'twentytwelve_customize_preview_js' );

Now this is where it gets tricky because one small mistake and you could break your site. So tread carefully and always keep a backup available. I just removed some widgets, comment functionality, rss feeds, author meta and a few other things, feel free to compare them to see what was removed. You could even remove all the inline comments as well. But just as it is I already saved 178 lines of code not to mention server stress from running un-needed functions.

<?php

/**
 * Sets up the content width value based on the theme's design and stylesheet.
 */
if ( ! isset( $content_width ) )
	$content_width = 625;

/**
 * Sets up theme defaults and registers the various WordPress features that
 * Twenty Twelve supports.
 *
 * @uses load_theme_textdomain() For translation/localization support.
 * @uses add_editor_style() To add a Visual Editor stylesheet.
 * @uses add_theme_support() To add support for post thumbnails, automatic feed links,
 * 	custom background, and post formats.
 * @uses register_nav_menu() To add support for navigation menus.
 * @uses set_post_thumbnail_size() To set a custom post thumbnail size.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_setup() {
	/*
	 * Makes Twenty Twelve available for translation.
	 *
	 * Translations can be added to the /languages/ directory.
	 * If you're building a theme based on Twenty Twelve, use a find and replace
	 * to change 'twentytwelve' to the name of your theme in all the template files.
	 */
	load_theme_textdomain( 'twentytwelve', get_template_directory() . '/languages' );

	// This theme styles the visual editor with editor-style.css to match the theme style.
	add_editor_style();

	// This theme supports a variety of post formats.
	add_theme_support( 'post-formats', array( 'aside', 'image', 'link', 'quote', 'status' ) );

	// This theme uses wp_nav_menu() in one location.
	register_nav_menu( 'primary', __( 'Primary Menu', 'twentytwelve' ) );

	/*
	 * This theme supports custom background color and image, and here
	 * we also set up the default background color.
	 */
	add_theme_support( 'custom-background', array(
		'default-color' => 'e6e6e6',
	) );

	// This theme uses a custom image size for featured images, displayed on "standard" posts.
	add_theme_support( 'post-thumbnails' );
	set_post_thumbnail_size( 624, 9999 ); // Unlimited height, soft crop
}
add_action( 'after_setup_theme', 'twentytwelve_setup' );

/**
 * Enqueues scripts and styles for front-end.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_scripts_styles() {
	global $wp_styles;

	/*
	 * Adds JavaScript for handling the navigation menu hide-and-show behavior.
	 */
	wp_enqueue_script( 'twentytwelve-navigation', get_template_directory_uri() . '/js/navigation.js', array(), '1.0', true );

	/*
	 * Loads our special font CSS file.
	 *
	 * The use of Open Sans by default is localized. For languages that use
	 * characters not supported by the font, the font can be disabled.
	 *
	 * To disable in a child theme, use wp_dequeue_style()
	 * function mytheme_dequeue_fonts() {
	 *     wp_dequeue_style( 'twentytwelve-fonts' );
	 * }
	 * add_action( 'wp_enqueue_scripts', 'mytheme_dequeue_fonts', 11 );
	 */

	/* translators: If there are characters in your language that are not supported
	   by Open Sans, translate this to 'off'. Do not translate into your own language. */
	if ( 'off' !== _x( 'on', 'Open Sans font: on or off', 'twentytwelve' ) ) {
		$subsets = 'latin,latin-ext';

		/* translators: To add an additional Open Sans character subset specific to your language, translate
		   this to 'greek', 'cyrillic' or 'vietnamese'. Do not translate into your own language. */
		$subset = _x( 'no-subset', 'Open Sans font: add new subset (greek, cyrillic, vietnamese)', 'twentytwelve' );

		if ( 'cyrillic' == $subset )
			$subsets .= ',cyrillic,cyrillic-ext';
		elseif ( 'greek' == $subset )
			$subsets .= ',greek,greek-ext';
		elseif ( 'vietnamese' == $subset )
			$subsets .= ',vietnamese';

		$protocol = is_ssl() ? 'https' : 'http';
		$query_args = array(
			'family' => 'Open+Sans:400italic,700italic,400,700',
			'subset' => $subsets,
		);
		wp_enqueue_style( 'twentytwelve-fonts', add_query_arg( $query_args, "$protocol://fonts.googleapis.com/css" ), array(), null );
	}

	/*
	 * Loads our main stylesheet.
	 */
	wp_enqueue_style( 'twentytwelve-style', get_stylesheet_uri() );

	/*
	 * Loads the Internet Explorer specific stylesheet.
	 */
	wp_enqueue_style( 'twentytwelve-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentytwelve-style' ), '20121010' );
	$wp_styles->add_data( 'twentytwelve-ie', 'conditional', 'lt IE 9' );
}
add_action( 'wp_enqueue_scripts', 'twentytwelve_scripts_styles' );

/**
 * Creates a nicely formatted and more specific title element text
 * for output in head of document, based on current view.
 *
 * @since Twenty Twelve 1.0
 *
 * @param string $title Default title text for current view.
 * @param string $sep Optional separator.
 * @return string Filtered title.
 */
function twentytwelve_wp_title( $title, $sep ) {
	global $paged, $page;

	if ( is_feed() )
		return $title;

	// Add the site name.
	$title .= get_bloginfo( 'name' );

	// Add the site description for the home/front page.
	$site_description = get_bloginfo( 'description', 'display' );
	if ( $site_description && ( is_home() || is_front_page() ) )
		$title = "$title $sep $site_description";

	// Add a page number if necessary.
	if ( $paged >= 2 || $page >= 2 )
		$title = "$title $sep " . sprintf( __( 'Page %s', 'twentytwelve' ), max( $paged, $page ) );

	return $title;
}
add_filter( 'wp_title', 'twentytwelve_wp_title', 10, 2 );

/**
 * Makes our wp_nav_menu() fallback -- wp_page_menu() -- show a home link.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_page_menu_args( $args ) {
	if ( ! isset( $args['show_home'] ) )
		$args['show_home'] = true;
	return $args;
}
add_filter( 'wp_page_menu_args', 'twentytwelve_page_menu_args' );

/**
 * Registers our main widget area and the front page widget areas.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_widgets_init() {
	register_sidebar( array(
		'name' => __( 'Main Sidebar', 'twentytwelve' ),
		'id' => 'sidebar-1',
		'description' => __( 'Appears on posts and pages except the optional Front Page template, which has its own widgets', 'twentytwelve' ),
		'before_widget' => '<aside id="%1$s" class="widget %2$s">',
		'after_widget' => '</aside>',
		'before_title' => '<h3 class="widget-title">',
		'after_title' => '</h3>',
	) );

	register_sidebar( array(
		'name' => __( 'First Front Page Widget Area', 'twentytwelve' ),
		'id' => 'sidebar-2',
		'description' => __( 'Appears when using the optional Front Page template with a page set as Static Front Page', 'twentytwelve' ),
		'before_widget' => '<aside id="%1$s" class="widget %2$s">',
		'after_widget' => '</aside>',
		'before_title' => '<h3 class="widget-title">',
		'after_title' => '</h3>',
	) );

}
add_action( 'widgets_init', 'twentytwelve_widgets_init' );

/**
 * Extends the default WordPress body class to denote:
 * 1. Using a full-width layout, when no active widgets in the sidebar
 *    or full-width template.
 * 2. Front Page template: thumbnail in use and number of sidebars for
 *    widget areas.
 * 3. White or empty background color to change the layout and spacing.
 * 4. Custom fonts enabled.
 * 5. Single or multiple authors.
 *
 * @since Twenty Twelve 1.0
 *
 * @param array Existing class values.
 * @return array Filtered class values.
 */
function twentytwelve_body_class( $classes ) {
	$background_color = get_background_color();

	if ( ! is_active_sidebar( 'sidebar-1' ) || is_page_template( 'page-templates/full-width.php' ) )
		$classes[] = 'full-width';

	if ( is_page_template( 'page-templates/front-page.php' ) ) {
		$classes[] = 'template-front-page';
		if ( has_post_thumbnail() )
			$classes[] = 'has-post-thumbnail';
		if ( is_active_sidebar( 'sidebar-2' ) && is_active_sidebar( 'sidebar-3' ) )
			$classes[] = 'two-sidebars';
	}

	if ( empty( $background_color ) )
		$classes[] = 'custom-background-empty';
	elseif ( in_array( $background_color, array( 'fff', 'ffffff' ) ) )
		$classes[] = 'custom-background-white';

	// Enable custom font class only if the font CSS is queued to load.
	if ( wp_style_is( 'twentytwelve-fonts', 'queue' ) )
		$classes[] = 'custom-font-enabled';

	if ( ! is_multi_author() )
		$classes[] = 'single-author';

	return $classes;
}
add_filter( 'body_class', 'twentytwelve_body_class' );

/**
 * Adjusts content_width value for full-width and single image attachment
 * templates, and when there are no active widgets in the sidebar.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_content_width() {
	if ( is_page_template( 'page-templates/full-width.php' ) || is_attachment() || ! is_active_sidebar( 'sidebar-1' ) ) {
		global $content_width;
		$content_width = 960;
	}
}
add_action( 'template_redirect', 'twentytwelve_content_width' );

/**
 * Add postMessage support for site title and description for the Theme Customizer.
 *
 * @since Twenty Twelve 1.0
 *
 * @param WP_Customize_Manager $wp_customize Theme Customizer object.
 * @return void
 */
function twentytwelve_customize_register( $wp_customize ) {
	$wp_customize->get_setting( 'blogname' )->transport = 'postMessage';
	$wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage';
}
add_action( 'customize_register', 'twentytwelve_customize_register' );

/**
 * Binds JS handlers to make Theme Customizer preview reload changes asynchronously.
 *
 * @since Twenty Twelve 1.0
 */
function twentytwelve_customize_preview_js() {
	wp_enqueue_script( 'twentytwelve-customizer', get_template_directory_uri() . '/js/theme-customizer.js', array( 'customize-preview' ), '20120827', true );
}
add_action( 'customize_preview_init', 'twentytwelve_customize_preview_js' );

Like I said before there are some blogging features that can be used in different ways. So even though we are just scraping everything out, make sure you don’t want to “recycle” these functions to do other cool things with some tweaking. After all WordPress IS a blogging platform that is being used as a CMS or static site so technically everything is being recycled and has a redefined purpose. There is still a lot you can do but this is a good place to stop and pause. Consider what functionality you want or want to reuse in different ways to give your CMS or static site that edge. Otherwise just apply the same tactics as above to the rest of the template files remaining in the twentytwelve theme directory.

Feel free to correct me, or give feedback! Thanks for reading!

Advanced Custom Fields Integration

Advanced Custom Fields

In this video tutorial I take you through the integration of Advanced Custom Fields into WordPress. Advanced Custom Fields is a WordPress plugin that allows you to add custom fields to your posts & pages. This is by far the best plugin I have found to do this and it has enabled me to take my client work to the next level. With this plugin its a breeze to make a whole site customizable without it taking all day. There is although a slight learning curve. You can’t complain though because it gives you so much power to customize your themes.

ACF (Advanced Custom Fields) has over 20 field types from uploading files to date pickers. This plugin is free, but has a few paid add-ons… one of which is repeater. Repeater is amazing because it allows you to let the end user decide how many fields he wants to repeat. So for instance an agenda, or speakers for an event. These types of things are always changing and have different amounts even day to day as updates are made. Using repeater you could put that kind of control into the hands of your client and not have to worry about the length of certain fields. This is also great for slideshows so you don’t have to specify the amount of slides you should have, its flexible. Originally this functionality was baked into the main plugin files and to unlock the repeater field you would just have to input a code key, but recently due to some WordPress policy changes ACF was forced to remove this “baked in” functionality and now ACF Repeater exists as a separate plugin that needs to be installed.

So here is the tutorial video. I hope you enjoy and I welcome any feedback. FYI the first few minutes I go off on a tangent on some other minor update to the site. I originally recorded this as to just capture me working on a live site doing day to day updates but I really ended up focusing on ACF.

To download ACF go here: Advanced Custom Fields

Password Protect Custom Templates in WordPress

Password Protection in Wordpress

It seems that the built in password-protect function of WordPress only protects the <?php the_content(); ?> portion of the post. But what about custom content within a custom template such as advanced custom fields? I ran into this issue and it took me a while to find a proper solution. There are many solutions out there that people say work but the didn’t work for me. The only what that did was the following:

<?php if ( post_password_required() ) { 

  echo get_the_password_form(); 

} else { ?>

  'Password Protected Custom Content'

<?php } ?>

This shows only the form on password protected pages, and once the form is entered it shows the custom content. Make sure you are not logged in when testing the page because I believe that it will automatically skip the password protection for logged in users. Also clear your cache after each test if you are using a caching plugin. Clear both the plugin cache and your browser cache. Test on another computer as well to be sure. Don’t make the same mistake I did! I always used to think that if it worked on my computer it should work on other peoples computers. That is just lazy thinking.

Anyway if you have any questions/concerns leave a comment.

This solution was found in the comments of this post.