Explanations and Examples

This section contains expanded explanations and examples for required items. This should be seen as a supporting document only to required items.

Code Code

Required: Have a valid DOCTYPE declaration and include language_attributes.

<!DOCTYPE html>
<html <?php language_attributes(); ?>>

Required: no shortcodes
The use of the add_shortcode() function is not allowed in themes as shown below:

add_shortcode( 'shortcode_name', 'shortcode_callback_func' );

Required: No removing or modifying non-presentational hooks.

remove_action( 'wp_head', 'wp_generator' );
remove_action( 'wp_head', 'feed_links_extra', 3); 
remove_action( 'wp_head', 'feed_links', 2); 

remove_action( 'admin_notices', 'update_nag', 3 );
remove_action( 'network_admin_notices', 'update_nag', 3 );

remove_filter( 'the_content','wpautop' );

add_filter( 'show_admin_bar', '__return_false' );

Top ↑

Core Functionality and Features Core Functionality and Features

Use get_template_directory() rather than TEMPLATEPATH to return the template path.

require_once( trailingslashit( get_template_directory() ) . 'inc/example.php' );

Use get_stylesheet_directory() rather than STYLESHEETPATH to return the stylesheet path.

require_once( trailingslashit( get_stylesheet_directory() ) . 'inc/example.php' );

This example should come with an additional warning to check if the file exists first if not used in a child theme.

Include comments_template().

comments_template();

Should be called in at least all singular views.

Top ↑

Plugin Territory Plugin Territory

Examples of plugin territory functionality:

  • Analytics or tracking support
  • SEO options
  • Content sharing buttons
  • Contact forms
  • Non-design related meta boxes
  • Resource caching
  • Dashboard widgets in the admin area

Top ↑

Documentation Documentation

Action hook

/*
 * Fires before the opening #page tag
 */
function theme_before_page(){
    do_action( 'theme_before_page' );
}

Filter hook

/*
 * Returns a specified width for the slider
 * 
 * Usage:
 * add_filter( 'theme_slider_width', 'my_callback' );
 * function my_callback(){
 *     return 755;
 * }
 */
$width = intval( apply_filters( 'theme_slider_width', 600 ) );

Top ↑

Favicons Favicons

The site icon feature in the wp-admin appearance>customizer>site-identity provides favicons. Backwards compatible support for favicons is not necessary since the feature was introduced to core more than two versions ago in WordPress 4.3.

Theme authors do not need to call wp_site_icon() directly as it is already hooked on wp_head.

The core function wp_site_icon() outputs a 32×32 favicon, a 192×192 Android/Chrome icon, a 180×180 Apple icon, and a 270×270 Microsoft icon.

Top ↑

Language Language

The text domain is required to be listed in the theme’s style.css head comment block. The text domain name should be generated from the theme slug. Example:

Theme Name: Mim's Debacle
Text Domain: mims-debacle

Theme authors have the choice of including their own language packs which will supersede the ones WordPress will self-install.
Here is an example how the text domain is loaded:

add_action( 'after_setup_theme', 'theme_review_setup' );
function theme_review_setup(){
    load_theme_textdomain( 'theme-slug', get_template_directory() . '/languages' );
}

For child themes loading the text domain would be:

add_action( 'after_setup_theme', 'theme_review_child_domain', 11 );
function theme_review_child_domain(){
    load_child_theme_textdomain( 'child-slug', get_stylesheet_directory() . '/languages' );
}

If a theme author chooses to include a POT file in their theme it needs to be kept up to date with all translation strings.

Top ↑

Licensing Licensing

Top ↑

Stylesheets and Scripts Stylesheets and Scripts

All stylesheets must be enqueued with wp_enqueue_style. The following example is not allowed:

<link type="text/css" rel="stylesheet" href="<?php echo get_stylesheet_uri(); ?>" />

The correct way would be to call wp_enqueue_style() from a function that is hooked on the wp_enqueue_scripts action:

add_action( 'wp_enqueue_scripts', 'theme_review_css' );
function theme_review_css() {
    wp_enqueue_style( 'theme-style', get_stylesheet_uri() );
}

Printing internal styles using <style> tags directly in the header.php is not allowed. The correct way would be to use a function that calls wp_add_inline_style and is hooked on the wp_enqueue_scripts action:

add_action( 'wp_enqueue_scripts', 'theme_review_styles' );
function theme_review_styles() {
        $custom_css = "
                .mycolor{
                        background: red;
                }";
        wp_add_inline_style( 'theme-style', $custom_css );
}

That would print the content of the $custom_css variable inside style tags directly after the stylesheet with the handle ‘theme-style’ is printed in the head.

All script files must be enqueued. The following example is not allowed:

<script type="text/javascript" src="<?php echo get_template_directory_uri(); ?>/js/theme-slider.js"></script>

The correct way would be to call wp_enqueue_style() from a function that is hooked on the wp_enqueue_scripts action:

add_action( 'wp_enqueue_scripts', 'theme_review_slider_options' );
function theme_review_slider_options(){
    wp_enqueue_script( 'theme-slider', get_template_directory_uri() . '/js/theme-slider.js', array( 'jquery' ) );
    wp_enqueue_script( 'theme-slider-init', get_template_directory_uri() . '/js/init.js', array( 'jquery', 'theme-slider' ) );
    // get user options
    $options = array();
    $options['autoplay'] = esc_attr( get_theme_mod( 'slider-autoplay', true ) );
    $options['navigation_style'] = esc_attr( get_theme_mod( 'nav-style', 'circles' ) );
    
    wp_localize_script( 'theme-slider-init', 'themeSliderOptions', $options );
}

Printing scripts using <script> tags directly in templates is not allowed. The correct way would be to use a function that calls wp_add_inline_script and is hooked on the wp_enqueue_scripts action:

function theme_review_add_inline_script() {
   $script = 'try{Typekit.load({ async: true });}catch(e){}';
   wp_add_inline_script( 'typekit', $script );
}
add_action( 'wp_enqueue_scripts', 'theme_review_add_inline_script' );

That would print the content of the $script variable inside script tags directly after the script with the handle ‘typekit’ is printed in the head or footer.

Top ↑

Themes are not allowed to have “obtrusive” upselling. The following are a few examples:

  • Global notifications in the admin area are not allowed. Notifications must restricted to specific pages.
  • Only one sub-page is allowed under the Appearance section in the admin sidebar.
  • Only one link on the top level in the customizer is allowed. This must be done using the customizer API(no injecting via JavaScript). Example. Further unobtrusive links are allowed in a separate section.
  • No options or panels/sections can be locked behind a paywall. All settings in a theme must work.

Top ↑

Templates Templates

Required: If used in theme, standard template files are required to be called using the correct template tag:

File Template tag
header.php get_header()
footer.php get_footer()
sidebar.php get_sidebar()
searchform.php get_search_form()
comments.php comments_template()