Menu Search
Jump to the content X X
Smashing Conf Barcelona 2016

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. upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

New WordPress Power Tips For Template Developers And Consultants

It has been a big year for WordPress. If there were still some lingering doubts about its potency as a full-fledged content management system, then the full support for custom taxonomies1 and custom post types2 in WordPress 3.0 core should have put them to rest. WordPress 3.1 took those leaps one step further, polishing custom taxonomies with multi-taxonomy query support3, polishing custom post types with native template support for archives and feeds4, and introducing features (like the “admin bar”) that make it easier to quickly edit and add content from the front end.

In the broader community, we’ve seen incredible plug-in suites such as BuddyPress5 mature, and even the emergence of independent WordPress-dedicated hosting services, such as page.ly6. To celebrate WordPress’s progress, let’s review some new tips that can help template developers and consultants up their game even further.

Foreword for New Developers: What is a “Hook”? Link

Most of these tips take advantage of core WordPress “hooks.” Hooks are points in the code that allow any number of outside functions to “hook in” and intercept the code in order to add to or modify behavior at a particular point. Hooks are the fundamental concept that enables virtually all plug-ins. WordPress has two kinds of hooks: actions and filters.

Action hooks are intended to allow developers to intercept certain activities and execute some additional functionality. For instance, when a new post is published, the developer may want to add some extra functionality, such as posting the title and a link to Twitter.

Filter hooks allow the developer to intercept and modify data that is being processed by WordPress for display or saving. For instance, the developer may want to inject an advertisement into the content before displaying the post on the screen.

Learn more about hooks on the official WordPress codex7.

The Underused Pagination Function Link

Many great plug-ins are in the official WordPress repository. But using fancy plug-ins to add fairly basic functionality to your theme is often like driving a tractor trailer to go around the block. There’s usually a lighter, smarter way: a bike or even a car. And while plug-ins are a fine solution for consultants who are staging a complete roll-out, they’re awkward solutions for theme developers who want to sell standalone templates.

WP-PageNavi8 is one of the most popular WordPress plug-ins; and no doubt it is well developed. It is ideal for those who are uncomfortable digging into WordPress code. But did you know that WordPress has a function built right into core that (with a bit of savvy about its parameters) can generate pagination links for everything from comments to post archives to post pages?

The function in question is paginate_links()9. (For those who like to fish around in the source, it’s on line 1954 of general-template.php in the wp-includes folder as of WordPress 3.1.)  Believe it or not, this underused function has been around since 2.1. Another function, paginate_comment_links()10, is actually a wrapper for this function that is designed specifically for paging comments, and it has been around since 2.7.

The function takes an array of parameters that make it versatile enough to use for any kind of paging:

  • base
    This is the path for the page number links, not including the pagination-specific part of the URL. The characters %_% will be substituted in that URL for the page-specific part of the URL.
  • format
    This is the “page” part of the URL. %#% is substituted for the page number. For example, page/%#% or ?page=%#%.
  • total
    The total number of pages available.
  • current
    The current page number.
  • show_all
    Lists all page links, instead of limiting it to a certain number of links to the left and right of the current page.
  • prev_next
    Includes the “Previous” and “Next” links (if applicable), just as you might normally do with the previous_posts_link() function.
  • prev_text and next_text
    Text to put inside the “Previous” and “Next” links.
  • end_size
    The number of page links to show at the end. Defaults to 1 (e.g. 1 2 3 … 10).
  • mid_size­
    The number of pages to show on either side of the current page. Defaults to 2 (example: 1 … 3 4 5 6 7 … 10).
  • type
    Allows you to specify an output style. The default is “plain,” which is just a string of links. Can also be set to list (i.e. ul and li representation of links) and array (i.e. returns an array of page links to be potentially outputted any way you like in code).
  • You can also add query arguments and fragments.

Because the function takes all of the information needed to generate page links, you can use it for pretty much any pagination list, as long as you have some key information, such as the number of pages and the current page. Let’s use this function to generate pagination links for an article archive such as a category or main post index:

// get total number of pages
global $wp_query;
$total = $wp_query->max_num_pages;
// only bother with the rest if we have more than 1 page!
if ( $total > 1 )  {
     // get the current page
     if ( !$current_page = get_query_var('paged') )
          $current_page = 1;
     // structure of “format” depends on whether we’re using pretty permalinks
     $format = empty( get_option('permalink_structure') ) ? '&page=%#%' : 'page/%#%/';
     echo paginate_links(array(
          'base' => get_pagenum_link(1) . '%_%',
          'format' => $format,
          'current' => $current_page,
          'total' => $total,
          'mid_size' => 4,
          'type' => 'list'

Here’s the HTML generated by that code on the first of 10 posts pages:

<ul class='page-numbers'>
     <li><span class='page-numbers current'>1</span></li>
     <li><a class='page-numbers' href=''>2</a></li>
     <li><a class='page-numbers' href=''>3</a></li>
     <li><a class='page-numbers' href=''>4</a></li> 
     <li><a class='page-numbers' href=''>5</a></li>
     <li><span class='page-numbers dots'>...</span></li>
     <li><a class='page-numbers' href=''>10</a></li>
     <li><a class='next page-numbers' href=''>Next &raquo;</a></li>

Here’s a screenshot of the pagination on m62 visualcommunications, built using the em>paginate_links function.


“I Wish Posts Were Called Articles For My Client.” Link

Have you ever wished you could change the wording of a built-in menu item or notification? If you’re a bit WordPress-savvy, you may have considered generating your own translations file. But you might not know that you can actually “hook” the translation functions in WordPress, capturing their input and modifying their output.

Be careful with this one. The code you put in this hook will run every time WordPress runs a string through its translation filters. Complex cases and conditionals could add a considerable amount of overhead, especially when loading pages filled with translation strings, such as the administrative pages. But if you just want to rename one thing that confuses your client (for example, maybe changing “Posts” to “Articles” for that corporate client who doesn’t “blog” yet), then these hooks can be very handy.

// hook the translation filters
add_filter(  'gettext',  'change_post_to_article'  );
add_filter(  'ngettext',  'change_post_to_article'  );

function change_post_to_article( $translated ) {
     $translated = str_ireplace(  'Post',  'Article',  $translated );  // ireplace is PHP5 only
     return $translated;

Redirect Failed Log-Ins Link

Adding a log-in form to the front end of WordPress is pretty easy. WordPress 3.0 gave us the flexible wp_login_form()12 function, which displays a log-in form that can be customized with a number of arguments. By default, it will redirect the user back to the current page upon successful authentication, but we can also customize the redirect location.

wp_login_form(array( 'redirect' => site_url() ));  // will redirect back to the website’s home page

There’s just one problem: it will only redirect upon successful authentication! If your idea was to hide the default WordPress log-in screen, then sending users who fail at a log-in attempt back to the default log-in screen probably isn’t ideal. Here’s a hook and some code that you can put in your functions.php file that will redirect failed log=ins to any location of your choosing.

add_action( 'wp_login_failed', 'my_front_end_login_fail' );  // hook failed login

function my_front_end_login_fail( $username ) {
     $referrer = $_SERVER['HTTP_REFERER'];  // where did the post submission come from?
     // if there's a valid referrer, and it's not the default log-in screen
     if ( !empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin') ) {
          wp_redirect( $referrer . '?login=failed' );  // let's append some information (login=failed) to the URL for the theme to use

Adding Excerpts to Pages Link

With the addition of support for custom post types, content types (including the built-in Post and Page types) are more like abstract objects. Each content type can support any number of core features, such as the HTML editor, titles, featured images and so forth. One of these core features is the “excerpt.” By default, Pages do not support excerpts. Did you know that adding excerpt support to the built-in Page type is as simple as adding a single line of code?

add_action( 'init', 'my_add_excerpts_to_pages' );
function my_add_excerpts_to_pages() {
     add_post_type_support( 'page', 'excerpt' );

Technically, that was a couple of lines of code, but many themes already hook init, so the hook might not be necessary.

Add Body Classes Based on Special Conditions Link

If a theme is well constructed, then it would use the body_class()13 function to automatically generate classes for the body tag based on the properties of the page being viewed, like category, category-3, and logged-in.

Some websites may have sections that should share some styling but aren’t unified by any of the default classes generated by body_class. Say we want page ID 7, category ID 5 and the archive for the tag neat to share the body class neat-stuff, so that we can add a number of styling properties to them all without cluttering the style sheet.

Luckily, we can hook the body_class() output!

add_filter( 'body_class', 'my_neat_body_class');
function my_neat_body_class( $classes ) {
     if ( is_page(7) || is_category(5) || is_tag('neat') )
          $classes[] = 'neat-stuff';

     return $classes; 

“You Can Have Settings Access, But Don’t Say We Didn’t Warn You!” Link

Clients often expect full administrative access (and rightly so), including access to settings pages. Let’s look at how we can hook admin “notices” (those warning boxes generated by some plug-ins) to send some warnings to administrative users when they are on settings pages.

add_action( 'admin_notices', 'my_admin_notice' );
function my_admin_notice(){
     global $current_screen;</div>
     if ( $current_screen->parent_base == 'options-general' )
          echo '<div><p>Warning - changing settings on these pages may cause problems with your website’s design!</p></div>';

With WordPress increasingly being used for full website implementations, the blog roll and links feature is being used less and less. Thankfully, a new, little-known function14 added in WordPress 3.1 makes it very easy to remove unwanted menu items such as “Links.”

add_action( 'admin_menu', 'my_admin_menu' );

function my_admin_menu() {

Take Out the Dashboard News Feeds… and Add a New One of Your Own Link

If you build WordPress websites for clients, then the number of WordPress news feeds loaded by default in the dashboard might be an annoyance. If you’re clever, you might just inject some of your own client’s news.

add_action('wp_dashboard_setup', 'my_dashboard_widgets');
function my_dashboard_widgets() {
     global $wp_meta_boxes;
     // remove unnecessary widgets
     // var_dump( $wp_meta_boxes['dashboard'] ); // use to get all the widget IDs
     // add a custom dashboard widget
     wp_add_dashboard_widget( 'dashboard_custom_feed', 'News from 10up', 'dashboard_custom_feed_output' ); //add new RSS feed output
function dashboard_custom_feed_output() {
     echo '<div class="rss-widget">';
          'url' => '',
          'title' => 'What's up at 10up',
          'items' => 2,
          'show_summary' => 1,
          'show_author' => 0,
          'show_date' => 1 
     echo "</div>";


If you build WordPress websites for clients, then you should certainly make sure that WordPress gets its due. It wouldn’t hurt to sneak in a little credit to your agency either.

add_filter( 'admin_footer_text', 'my_admin_footer_text' );
function my_admin_footer_text( $default_text ) {
     return '<span id="footer-thankyou">Website managed by <a href="">10up</a><span> | Powered by <a href="">WordPress</a>';

Further Reading Link

Here are more tips for developers who build websites for clients:

More WordPress power tips from Smashing Magazine:

(al) (il)

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
SmashingConf Barcelona 2016

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to top Tweet itShare on Facebook


Jacob M (Jake) Goldman is the owner of 10up LLC, a web development and strategy agency with a focus on making content management easy and fun. 10up's clients range from small local businesses to major VIP clients like TechCrunch. You can find his insights and development tips by following him on Twitter @jakemgold

  1. 1

    Suberb Tips Jacob, Never heard about any of them till now.

  2. 2

    Useful tips, thanks!

    • 3

      It is really good article to learn more about WordPress and especially the “screenshot of the pagination”. :-)

  3. 4

    Đurica Bogosavljev

    May 10, 2011 1:03 am

    Great tips with good examples! Bookmarked!!
    Hope you will prepare more of these power tips for WordPress Template Developers in the future!

  4. 5

    Christophe Debruel

    May 10, 2011 1:26 am

    Wow nice list :D some good stuff in there that I probably use immediatly!

  5. 6

    Awesome tips – thanks for sharing! I’m looking forward for the next part ;)

  6. 7

    I found a nice way to add custom styles to the WYSIWYG editor:

    It adds a new styles dropdown which adds classes to selected text in the editor.

  7. 8

    Vaibhav Jain

    May 10, 2011 1:57 am

    Feels so good to see these features in WordPress.
    However, I feel they are pretty much similar to Drupal. The taxonmoy structure and the way hooks are implemented.
    They way hook are implemented in drupal is a bit different but the logic is all the same.
    But still WordPress Rocks !!!

  8. 9

    Great write up.

    One thing I wanted to correct is that empty() function only checks variables, and if you try to check anything other than variable with empty() function, it will cause a parse error; something like:

    Can’t use function return value in write context

    I’m talking about the code provided under the section “The Underused Pagination Function”.

    I would write it like this:

    // get total number of pages
    global $wp_query;
    $total = $wp_query->max_num_pages;
    // only bother with the rest if we have more than 1 page!
    if ( $total > 1 ) {
    // get the current page
    if ( !$current_page = get_query_var('paged') )
    $current_page = 1;
    // structure of “format” depends on whether we’re using pretty permalinks
    $permalink_structure = get_option('permalink_structure');
    $format = empty( $permalink_structure ) ? '&page=%#%' : 'page/%#%/';
    echo paginate_links(array(
    'base' => get_pagenum_link(1) . '%_%',
    'format' => $format,
    'current' => $current_page,
    'total' => $total,
    'mid_size' => 4,
    'type' => 'list'

    Thanks for the awesome post. Waiting for more neat posts like this, Jacob.

    • 10

      Thanks for the help. I was getting that error message and had no idea where to begin!

  9. 11

    i think there’s a typo here :

    add_action( ‘admin_notices’, ‘my_admin_notice’ );
    function my_admin_notice(){
    global $current_screen;</div>
    if ( $current_screen->parent_base == ‘options-general’ )
    echo ‘Warning – changing settings on these pages may cause problems with your website’s design!’;

    isn’t “global $current_screen;</div>” supposed to be global “$current_screen;”

    • 12

      wops somehow the tag didn’t show up. I was talking about this particular section : “You Can Have Settings Access, But Don’t Say We Didn’t Warn You!”

      where there is extra div at the end of this line global $current_screen;

  10. 13

    yeah.. i have just look like this solution…

  11. 14

    I’ve used and loved WordPress for nearly five years now, but am feeling its limits more recently, especially with options like Expression Engine out there. For clients that want a custom post type with multiple fields, it just gets too complicated. No ability to have multiple rich text fields, and having the other custom fields limited to plain text instead of, say, a calendar or image selection, has made me look at alternatives for more involved projects.

    • 15

      C’mon, last time I developed a theme I was able to create lots of WYSIWYG fields via custom metaboxes, not only for custom post types but for standard posts and pages too.

      Er… and that ExpressionEngine thing pisses me off in the first place. They want some of every penny I earn from a client work.

      • 16

        Mind sharing how?

        • 17

          phil jackson

          May 10, 2011 12:51 pm

          ‘morefields’ plugin?

        • 18

          If you’re familiar with WP code, you can create metaboxes. Just add the class theEditor to the textarea you want to apply a WYSIWYG and you’re good to go.

          Also you can use a plugin. there are few plugins which can do this including the one mentioned by Phil Jackson in the above comment.

          • 19

            Also, Custom Field Template is fantastic. There’s a slight learning curve but it allows you to do almost anything using the WP custom fields, including rich text, selects, radio buttons, and assigning the template you create to a particular post type if you wish. I couldn’t live without it.


    • 20

      I would suggest giving Drupal a spin –> proprietary CMS’s like Expression Engine and (gasp) Business Catalyst are really out of the realm of this article (they do take your hard earned money). Why –> because their License wouldn’t permit developers from selling “themes”.

      Also it is kind of funny to see word press now doing what Drupal was years ago —
      I think drupal is ahead of the curve — as a software product. Of course WordPress does have more people making themes, and is easier to understand with an “out of the box” install.

      • 21

        I’m not bashing Drupal because I know there’re a lot of dedicated and smart people working on it. However, I think WP is just allowing for functionality common to all CMS’s, which it wasn’t until very recently. I’ve built several Drupal sites and I found the process extraordinarily painful. So, when WP 2.8 came out I jumped on it and never looked back. The documentation is crystal clear, the support forums are filled with great people and the code is well-documented and easy to find. WP may not be as robust as Drupal, but in the 3 years I’ve been working with it I’ve not found it to be limiting and I keep discovering more things I can do with it.

    • 22

      It looks like the author of this article developed a plugin to do just this…

      I haven’t tried it, so I can’t really vouch for it – but the guy has some credibility for writing here, so check it out! Looks like he has some other quality plugins, too.

  12. 23

    Excellent, much needed, will use. Thanks!

  13. 24

    I wish I could have multiple homes based on categories for example. i.e: (home) and (games home), like a news portal.

  14. 25

    Nice, I love playing around with WordPress’ core functions via hooks, I just wish there was better documentation for all of them! You’ve brought up a couple of good ones…like the admin_menu hook, I recently developed a plugin for our website which utilized hooks and CSS to style the Admin section of WordPress depending on user roles. It probably would have been programmatically correct to use those hooks to disable menu items, but I resorted to my good old friend, display: none;

    Don’t judge me! Now that I know about a few more of these, I’ll be using them instead of a CSS solution! Thanks!

  15. 26

    Jeffrey Friend

    May 10, 2011 6:44 am

    Great tips! Love the “Articles” tip, and especially the “Admin Notice”! I’ve had a client or two decide to “see what happens”. It always turns out badly for them! ;-)

  16. 27

    well written tips! thanks!

  17. 28

    These are amazing and some (like renaming posts), I’ve been wondering about for a while.

    Unsetting the Dashboard panels is much easier this way though (and adding the action to the “admin_menu” gets all of them this way):

    add_action( ‘admin_menu’, ‘remove_meta_boxen’ );
    function remove_meta_boxen() {
    remove_meta_box( ‘dashboard_secondary’, ‘dashboard’, ‘normal’ ); //Other WordPress News
    remove_meta_box( ‘dashboard_right_now’, ‘dashboard’, ‘normal’ );
    remove_meta_box( ‘dashboard_incoming_links’, ‘dashboard’, ‘normal’ );
    remove_meta_box( ‘dashboard_plugins’, ‘dashboard’, ‘normal’ );
    remove_meta_box( ‘dashboard_quick_press’, ‘dashboard’, ‘normal’ );
    remove_meta_box( ‘dashboard_primary’, ‘dashboard’, ‘normal’ ); //Wordpress Blog
    remove_meta_box( ‘dashboard_recent_drafts’, ‘dashboard’, ‘normal’ );
    remove_meta_box( ‘dashboard_recent_comments’, ‘dashboard’, ‘normal’ );


  18. 29

    Michael Gorman

    May 10, 2011 7:32 am

    I especially loved the warning on the settings pages. Thanks!

  19. 30

    Here’s another great tip from a WordPress customer: Screenshots, Screenshots, examples, Screenshots! Take a couple of extra minutes use whatever graphical editing software you can get your hands on and take screenshots.

  20. 31

    just tried the redirect wrong login snippet works great till someone enters wrong credentials more than once. Small fix which works for me add_action( ‘wp_login_failed’, ‘my_front_end_login_fail’ ); // hook failed login

    function my_front_end_login_fail( $username ) {
    $referrer = $_SERVER[‘HTTP_REFERER’]; // where did the post submission come from?
    // if there’s a valid referrer, and it’s not the default log-in screen
    if ( !empty($referrer) && !strstr($referrer,’wp-login’) && !strstr($referrer,’wp-admin’) && !strstr($referrer, ‘failed’) )
    wp_redirect( $referrer . ‘?login=failed’ ); // let’s append some information (login=failed) to the URL for the theme to use
    wp_redirect( $referrer); //if user entered credentials wrong again just use the login failed referrer again


↑ Back to top