Keith Devon

Menu

Category: tuts

How (and why) to use Schema.org on your WordPress website

Search engines have a big problem. There is so much data out there and it’s hard to work out what is what.

Humans are great at inferring the context of web content, but this is much more difficult for Google, Bing, Yahoo!, etc..

That’s why the biggest search engines have come together to create a standard way to add structured data to your website. What they have created is called Schema.org. In their words:

Schema.org is a joint effort, in the spirit of sitemaps.org, to improve the web by creating a structured data markup schema supported by major search engines

https://schema.org/docs/faq.html#0

Why you should be using Schema.org markup

You’re probably still wondering why you should take the time to add Schema markup to your website. The simple answer is that it will probably improve your search traffic. Google, and other search engines, want to display the most relevant search results. If it’s clear what your web page is about, then it’ll have more confidence in it’s relevance. Here’s what they have to say on the topic:

These projects help you to surface your content more clearly or more prominently in search results.

https://schema.org/docs/faq.html#9

Google back this up on their website:

When your web pages include structured data markup, Google (and other search engines) can use that data to index your content better, present it more prominently in search results, and surface it in new experiences like voice answers, maps, and Google Now.

https://developers.google.com/structured-data/

While Google won’t come out and say that using Schema.org will definitely have a positive impact on your search rankings, they don’t deny it either (see their ambiguous answer here: https://www.youtube.com/watch?t=57&v=OolDzztYwtQ). But what they do say is that it’s likely to help your content to be presented more prominently, which is often as part of rich snippets (I’ll explain these below).

While using Schema.org markup may not improve your search rankings (yet!) it will help to give your content more prominence on search results pages.

Is everyone using Schema.org markup?

In my experience Schema.org markup is still underused. There are clear benefits, yet adoption seems to be slow. In fact a study by searchmetrics in 2014 found that only 0.03% of domains tested had Schema.org integration.

THIS IS A GOOD THING! It means that you can easily get ahead of your competitors instead of always playing catch-up.

Don’t just take my word for it. The SEO experts over at Moz agree…

If someone told you that there was a quick and easy way that many of you could improve your SERP CTR for minimal effort, you’d all stop in your tracks and give them full attention. Yet, Schema.org and rich snippets are still horribly under-utilized.

http://moz.com/blog/schema-examples.

Schema.org and rich snippets

Let’s have a look at how the search engines are using Schema.org data today. The most visible examples are reviews. Search for “cube agree gtc reviews” (it’s a bike) in Google and you’ll get something like this:

Search results page for bike review

See all of those stars? These are what’s known as “rich snippets”. That content is being pulled from Schema.org data. How do I know? Let’s have a look at the code.

The top result is from cyclingweekly.co.uk (a site I worked on). If we click on that link and inspect the code we can see this:

Cycling weekly review code

Can you see the itemtype="http://schema.org/Rating"? That’s the markup that has been added to give context to the content. The rating itself is defined by the meta tags below, also with Schema.org markup.

Let’s look at the BikeRadar code (the third search result) to see if they are using it too.

Bike Radar review code

Yep! There it is again. I don’t think there’s any coincidence that these two websites are at the top of the search rankings. Don’t get me wrong, there are other factors at play, but clearly Google is making use of this data to provide relevant search results.

I’m sure you don’t all have review based websites, so let’s look at another example. Here are the top search results for “Kawehi tickets”:

Search results for Kawehi tickets

Google knows the date, and venue of the next three events near me. Again, these sites are using Schema.org markup.

Reviews and events are just two common uses. Some of the other prominent uses are:

I bet some of you are thinking “none of those apply to my business”. You might be right, but there are other Schema.org ‘properties’ that you can use.

LocalBusiness

https://schema.org/LocalBusiness

You can add markup that explains your business. This is perfect for smaller local businesses, or local branches of larger organisations. Some of the data that you can pass include (but not limited to):

Blog and BlogPosting

If you’re using WordPress there’s a good chance you have a blog on your website. Schema.org provides Blog and BlogPosting properties that you can use to add structured data to your posts. You can add:

  • Headline
  • Text
  • Date published
  • Author
  • and a lot more

Adding Schema.org markup to your WordPress website

Because Schema.org markup is so closely integrated with your site content and code, it’s not always an easy addition to your site.

There seem to be some plugins that claim to help, https://wordpress.org/plugins/tags/schemaorg, but I don’t have any experience with those, and I’d question how exactly they can know where that data is within your theme code.

Another option is themes with Schema.org baked in. These are most commonly directory style themes.

Finally you could ask your developer to add some schema markup to your theme where you think it will be appropriate and useful. It actually doesn’t take long to add the appropriate markup, so shouldn’t be too costly, and it will avoid having to add yet another plugin.

Schema.org markup for a blog post

Let’s have a look at one of the most useful implementations of Schema.org markup – blog posts.

If you visit https://schema.org/BlogPosting you’ll see a long list of potential properties to add. I’m going to focus on the basics here, you can always add more depending on your content.

The first thing to do is to define the scope of your blog post as a ‘BlogPosting’. Your post might start like this:

<article itemscope itemtype="https://schema.org/BlogPosting">

Now let’s start adding some of the basic properties. Firstly, let’s add the ‘headline’. You can do so like this:

<h1 itemprop="headline"><?php the_title(); ?></h1>

Next we’ll add some of the post meta data, starting with the published date.

<time pubdate itemprop="datePublished" datetime="<?php the_time( 'c' ); ?>" content="<?php the_time( 'c' ); ?>">

<?php the_time( get_option( 'date_format' ) ); ?>

</time>

We could add more microdata here, like ‘pubdate’, but I’ve left that out for the sake of simplicity.

Tags and categories can also be given the Schema.org treatment:

<div>Categories: <span itemprop="about"><?php the_category(', '); ?></span></div>
<div>Tags: <span itemprop="keywords"><?php the_tags(''); ?></span></div>

We can also mark up the author information. Google has recently removed it’s ‘authorship’ rich snippets, but this data could still be used in the future.

<div itemprop="author" itemscope itemtype="https://schema.org/Person"><img itemprop="image" src="<?php echo get_avatar_url( get_avatar( get_the_author_meta( 'ID' ), 150 ) ); ?>" />
<span itemprop="name"><?php the_author();?></span>
</div>

I’ve used a custom function to get the author avatar URL. The code is from this WordPress Development question.

The last bit of Schema.org markup that we’ll add for now is the actual content of the blog post. This one is easy:

<div itemprop="text"><?php the_content(); ?></div>

The complete code would look something like this:

<article itemscope itemtype="https://schema.org/BlogPosting">
<header>
<h1 itemprop="headline"><?php the_title(); ?></h1>
<time pubdate itemprop="datePublished" datetime="<?php the_time( 'c' ); ?>" content="<?php the_time( 'c' ); ?>">
<?php the_time( get_option( 'date_format' ) ); ?>
</time>

<div>Categories: <span itemprop="about"><?php the_category(', '); ?></span></div>
<div>Tags: <span itemprop="keywords"><?php the_tags(''); ?></span></div>

<div itemprop="author" itemscope itemtype="https://schema.org/Person">
<img itemprop="image" src="<?php echo get_avatar_url( get_avatar( get_the_author_meta( 'ID' ), 150 ) ); ?>" />
<span itemprop="name"><?php the_author();?></span>
</div>

</header>

<div itemprop="text">
<?php the_content(); ?>
</div>

</article>

Does your site already use Schema.org?

If you’re wondering if your theme already has Schema.org (or other structured data) this is a brilliant tool: https://developers.google.com/structured-data/testing-tool/.

Closing thoughts

In my opinion structured data, including Schema.org is going to become more and more important. As the internet gets bigger search engines will have more content to sift through, and will have to deliver it in new ways. If your content is well structured, you’ll be at an advantage over your competition.

If you have any questions about Schema.org markup I’d love to hear from you.

Keith

Useful links

How to test your WordPress website performance

Website speed matters. Nobody likes browsing a slow website. If your site is slow, your visitors are more likely to leave and go to a competitor’s website.

It’s not just your users who like speedy websites, Google does too.

Today I recorded a video showing you two ways to test your website performance. Both methods use free, online tools and are really fast and easy to use.

Did you test your site? How did it do? Let me know in the comments, or email me at keith@keithdevon.com.

Using variables with WordPress translation functions

Today I wanted to be able to pass a custom field variable to the WordPress localization (l10n) functions. The custom field is a select field, so all the possible outputs are known.

WordPress uses PO and MO files for translations. These are generated by scanning the site for __() and _e() functions, with a programme such as Poedit, to generate the list of translatable strings.

Using variables in these functions, like _e($output, 'text-domain'), causes a problem. When the scan is done, there is no string to add to the PO file.

In my case, because the outputs are known, I created a file called manual-translations.php, included it from my functions.php file and added the translatable strings like:

__( 'String one', 'text-domain' );
__( 'Second string', 'text-domain' );
__( 'Stringy cheese', 'text-domain' );

Now when the site is scanned it picks these up and I can now add the translations in Poedit.

Hope that helps someone out there!

Setting up domains on WP Engine

Add domains to install

  1. Log in to my.wpengine.com
  2. Click on the install name
  3. Click on ‘Domains’
  4. Click ‘Add domain’
  5. Add the non-www version of the domain
  6. Click ‘Add domain’
  7. Add the www version of the domain

Change DNS at registrar

  1. Log in to my.wpengine.com
  2. Click on the install name
  3. Note the IP Address and CNAME of the install
  4. Log into the domain registrar
  5. Set the @ record to the IP address
  6. Set the CNAME www to the CNAME of the install

Resources

  • http://wpengine.com/support/how-to-configure-your-dns/
  • http://wpengine.com/support/find-ip/
  • http://wpengine.com/support/cname/
  • http://support.godaddy.com/help/article/680/managing-dns-for-your-domain-names

Full screen background images

I’m putting this here for my own sanity. If I had £1 for every time I’ve tried to solve this issue!

The goal here is to have a background image that covers the whole of the browser window. Ideally we want it to scale, stay centred, and keep it’s correct proportions.

My go-to article on this is Chris Coyier’s Perfect Full Page Background Images. I was trying the “Awesome, Easy, Progressive CSS3 Way”, but was having difficulty on IOS.

A bit more Googling brought me back to CSS-Tricks and to this thread where a solution is posted by k00ka. Here’s the CSS:

html {
background: url('http://placebear.com/1200/800') no-repeat center center fixed;
background-size: cover;
height: 100%;
overflow: hidden;
}

body {
height:100%;
overflow: scroll;
-webkit-overflow-scrolling: touch;
}

IE Compatibility view issues

I’ve run into issues a few times recently with Internet Explorer’s ‘Compatibility view’. Some of my standards compliant web pages were being broken by having this view enabled.

I found a solution via this stackoverflow page.

If you add the following to your <head> it will force IE to disable compatibility view:

<meta http-equiv="X-UA-Compatible" content="IE=edge" />

However, if IE thinks that your website is part of an intranet you’ll have to disable this manually in the browser. The only way to override that is to uncheck ‘Display Intranet sites in Compatibility View’ checkbox in ‘Tools’ > ‘Compatibility View settings’.

Update

Wesley Burden (@wesleyburden) shared this little function with me:

add_action( 'send_headers', 'add_header_compatibility_mode' );

function add_header_compatibility_mode() {
header( 'X-UA-Compatible: IE=edge,chrome=1' );
}

Apparently this will override the IE settings and  disable compatibility even if part of an intranet. If you try it out let me know if it works.

Passing variables to get_template_part() in WordPress

This morning I needed to pass a variable to a file that I was including using the WordPress get_template_part function.

I was fiddling around with global variables when I thought there must be a better way. There is.

Locate and include

You can use the WordPress locate_template function within PHP’s include(). It’s done like this:

include(locate_template('your-template-name.php'));

All of the variables available in your current script will be available in that template file now too.

The PHP ternary operator

In my quest to master PHP, I’m going to start investigating some of the bits I’m unfamiliar with, and blogging about them.

This morning, I was reading through the excellent “Professional WordPress Plugin Development” by Brad Williams, Ozh Richards and Justin Tadlock (I’ve made a resolution to read a bit every couple of days). In the user settings section there is an example of a ternary operator.

$lang = $_POST['boj_adminlang_lang'] == 'es_ES' ? 'es_ES' : '';

Frankly, I’m embarrassed that I’ve come across this syntax so many times without taking the time to understand it. Especially because it is so simple.

The above code is short for:

if( $_POST['boj_adminlang_lang'] == 'es_ES' ) {
$lang = 'es_ES' ;
} else {
$lang = '' ;
}

I’ve written so many statements using the longhand version. Time to level up!

Custom Post Types

Last night I gave a presentation at the WordPress London meetup. I talked about custom post types in WordPress, something that has really excited me since WordPress 3. I’ve included the video, a rough transcript of the presentation and the slides at the bottom.

What we’ll cover

  • What are custom post types
  • When to use them
  • How to use custom post types
  • Taking things further
  • Resources

What are custom post types?

I’ve searched high and low on the internet for a decent definition of custom post types, with no luck. The best that I’ve seen is that they are really custom content types.

Replacing the word ‘posts’ with ‘content’ gives us a much better understanding of what custom post types are all about. The idea is that there is some content on your website that might not fit neatly into the typical page’ or ‘post’ mould. Think of the following examples:

  • Movies
  • Staff
  • Podcasts
  • Books
  • Products
  • Portfolio items
  • Testimonials, etc, etc.

Then why are they called custom post types?

Within WordPress there are already various post types: posts, pages, menus and revisions. With version 2.9 came the ability to define your own, ‘custom’, post type. These are stored in the wp_posts table. Hence custom post types.

When to use custom post types

Here is a fairly typical client request:

“I want to create a website for my holiday home rentals company. I have a portfolio of 20 properties that I want to be able to manage and update. Each property has the following information:

  • Name
  • Address
  • Short intro
  • Full property description
  • An image
  • Price per week
  • Number of rooms

I would like the user to able to sort the properties by ‘Price’ and ‘Number of rooms. I will also be blogging on the site.”

Without custom post types

In those dark days before WP 2.9 I probably would have used posts for the properties. I then would have created a category of ‘properties’ so that I could style those property posts differently than the regular blog posts. I then would have used custom fields for the meta data – rooms and price.

This used to work, but it was an ugly solution, a ‘hack’. The property posts would be mixed in with the regular blog posts both in the admin and the front-end.

Enter, custom post types

With custom post types we can separate our content into logical groups. Posts are now just chronological blog/news items again and properties have their own section.

This also makes theme development easier. The posts and properties are no longer lumped together, so no need to hack the index.php loop. New templates are available specifically for your properties post type too.

Basically, using custom post types is going to seriously improve workflow for both you and your client.

How to use custom post types

Creating your custom post type

Before I start, I have to tell you that there are ways to create custom post types on your WordPress site without having to touch a single line of code. There are several plugins and online code generators that will do it all for you. However, I strongly encourage you to have a go at this yourself. Even if this is the first bit of theme development that you have done, give it a go. You’ll have a much better idea of what’s going on and you’ll find it so satisfying.

Open up your theme’s functions.php file using your favourite text editor, and add the following:


add_action( 'init', 'create_my_post_types' );

function create_my_post_types() {
register_post_type( 'kdev_properties',
array(
'labels' => array(
'name' => __( 'Properties' ),
'singular_name' => __( 'Property' )
),
'public' => true,
'has_archive' => true,
'supports' => array('title','editor','excerpt','thumbnail'),
'rewrite' => array( 'slug' => 'property' ),
'register_meta_box_cb' => 'add_property_metaboxes',

)
);
}

This code is all we need to get custom post types working on our WordPress site. in fact, it’s more than we need, I’ve added a few lines, 11, 13 and 14, that aren’t essential but useful for what we’re trying to achieve.

Line 4 is where the magic starts, we’re registering our post type and giving it a name. I’ve prefixed the name with ‘kdev_’ to avoid clashes with any other plugins.

Line 6 starts the ‘labels’ array and at this point we’re only using two labels ‘name’ and ‘singular_name’. These will appear in our theme instead of the ugly ‘kdev_properties’. There are lots more labelling options, check them out here http://codex.wordpress.org/Function_Reference/register_post_type#Arguments.

Line 10 is telling WordPress to make the post type public, that is visible, in the admin and front-end. Strangely this defaults to false, so you must include it if you want to see your post type.

‘has_archive’ on line 11 is optional. I’m using it to tell WordPress that I will be using a custom archive template.

The ‘supports’ array on line 12 is where it starts to get interesting. Everything that you are familiar with from posts and pages are available to you here. I’m just enabling the elements that we’ll need for our property post type.

Line 13 enables a URL rewrite. This changes our URL structure from kdev_properties/propertyname to property/propertyname (assuming we’re using a ‘pretty’ permalink structure).

The last line, 14, is telling WordPress that I wish to use a custom meta box on this post type. this will be explained in greater detail later on.

Now log in to your WordPress admin area and you should see something similar to the following:

You can see that our custom post type, ‘properties’, has been added to the main menu, keeping it separate from posts and pages.

If you click on the ‘Properties’ link and then ‘Add New’ you will get to the following screen.

Here we can see the ‘supports’ array in action. We’ve added some useful functionality here but it’s also important to note what we’ve left out. The categories and tags that we are familiar with from posts are gone, as are page attributes, revisions, comments and discussions. This leaves us with a nice clean UI. There are no extraneous admin elements to distract the user.

Our code hasn’t just created a great admin screen, it’s also enabled us to view our custom post type live on the site. From the ‘Edit Post’ screen, click on ‘Preview’ to see what your post will look like (add some content first for a better effect!). You’ll see something like this:

That’s great so far, but the chances are that you’ll want your custom post type to look slightly different to regular posts. WordPress gives us two template files to do this; single-[posttype].php and archive-[posttype].php.

The single template will let you style your individual custom post types, in our case the single property page. It’s often easiest just to create the new template file (e.g. single-kdev_properties.php), in your theme directory, and copy and paste the code from your theme’s single.php file. Then you can make any changes that you require. Before you do that though, there are some more tricks that will help you make your custom post type really come to life!

The archive-[posttype].php template will create a page that displays a list of your custom posts. Using the same idea as above, you can copy and paste from your index.php file and edit from there. Remember the ‘has_archive’ argument that we added? That line is telling WordPress to use our custom archive file.

Congratulations! You’ve created your first custom post type. That wasn’t too hard was it? There is loads more that we can do with our custom post type.

Taking things further

Remember the original client request? She wanted to be able to add ‘price’ and ‘number of rooms’ data to her properties. Of course, we could just add this to the main text editor, but then it would be tricky to separate the data if we wanted to use it by itself. This is where custom meta boxes come in.

Custom meta boxes

Here’s where custom post types start to get really cool. We’re not limited to the ‘title’, ‘excerpt’, etc. that WordPress provides us with. We can add new boxes to our edit screen that accept any kind of data that we can think of.

Here’s an example of some meta boxes:

The first meta box is a simple text field, the second a radio button. You could have checkboxes, text-areas, TinyMCEs, etc. By now your imagination should be kicking in to show you the possibilities available!

We want two meta boxes, one for price and one for rooms. Here’s the code that we need to achieve this:


//Add custom meta box

// Add the Properties Meta Boxes

function add_property_metaboxes() {
add_meta_box('kdev_properties_rooms', 'Number of Rooms', 'kdev_properties_rooms', 'kdev_properties', 'side', 'default');
add_meta_box('kdev_properties_price', 'Price per week', 'kdev_properties_price', 'kdev_properties', 'side', 'default');
}

// Output the Property metaboxes

function kdev_properties_rooms() {
global $post;

$prop_rooms = get_post_meta($post->ID, '_rooms', true);

echo '<label>Rooms</label><input class="widefat" name="_rooms" type="text" value="' . $prop_rooms . '" />';
}

function kdev_properties_price() {
global $post;

$prop_price = get_post_meta($post->ID, '_price', true);

echo '<label>Price per week</label><input class="widefat" name="_price" type="text" value="' . $prop_price . '" />';
}

// Save the Metabox Data

function kdev_save_property_meta($post_id, $post) {
if ( 'kdev_properties' == get_post_type() ) {

if ( !current_user_can( 'edit_post' , $post ->ID )) return $post ->ID;

$property_meta['_rooms'] = $_POST['_rooms'];
$property_meta['_price'] = $_POST['_price'];

foreach ($property_meta as $key => $value) { // Cycle through the $property_meta array!
if( $post->post_type == 'revision' ) return; // Don't store custom data twice
$value = implode(',', (array)$value); // If $value is an array, make it a CSV (unlikely)
if(get_post_meta($post->ID, $key, FALSE)) { // If the custom field already has a value
update_post_meta($post->ID, $key, $value);
} else { // If the custom field doesn't have a value
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key); // Delete if blank
}
}
}

add_action('save_post', 'kdev_save_property_meta', 1, 2); // save the custom fields

This is a bit more complex and I won’t go through every line. Add this to your functions.php file and make sure that the variable names are correct (if you have used something other than ‘kdev_properties you’ll need to change it here too).

There are some arguments that you may wish to tinker with. Remember, you won’t learn if you don’t make mistakes, so don’t be scared. It’s always a good idea to make backups before you start experimenting though, especially with a live site.

Adding that code will give you something like this:

Check out those custom meta boxes on the right! Sweet.

As cool as it is to have custom meta boxes, they’re not going to do anything for you without a bit of work to your template files.

Open up one of your custom template files and add the following:


Price per week: £<!--?php echo get_post_meta(get_the_ID(), '_price', true); ?-->

Number of rooms: <!--?php echo get_post_meta(get_the_ID(), '_rooms', true); ?-->

The get_post_meta() function is creating all the magic here. It takes a few arguments, the post ID, the meta key, and whether to return a single string or an array (‘true’ will return the string).

I’ve added those lines to my custom archive template to get the following:

Nice work. Our custom post types have meta boxes and we have some pretty nifty templates. There’s one more part to the holy trinity of custom awesomeness…

Custom taxonomies

Taxonomies are ways to classify your data. If you’re familiar with WordPress you will already be using them; categories and tags. These are both taxonomies, but they are very general, and you’ll probably want to keep these for your blog posts.

For our custom post types we can create our own custom taxonomies. There are two main types; hierarchical and, erm, not.

Hierarchical taxonomies

Hierarchical taxonomies have the concept of parents and children, like categories. You can create tree like structures of nested classifications.

Non-hierarchical taxonomies

These are like post tags. They don’t have parents or children.

Creating a custom taxonomy

function my_register_taxonomies() {

register_taxonomy(
'area',
array( 'kdev_properties' ),
array(
'public' => true,
'labels' => array( 'name' => 'Area', 'singular_name' => 'Area' ),
'hierarchical' => true,
)
);
}

add_action( 'init', 'my_register_taxonomies' );

This is all we need to create a custom taxonomy for our custom post type. I’ve given it a name, assigned it to the ‘kdev_properties’ post type and given it some arguments. Again, have a play around. The code can be added to your functions.php file as before.

And so we have it. Well done for getting to the end!

Hopefully, you’ll be inspired to use custom post types on your next project. You’ll never look back, I promise.

Resources

http://codex.wordpress.org/Post_Types
http://codex.wordpress.org/Function_Reference/register_post_type

Plugins

http://wordpress.org/extend/plugins/custom-post-type-ui/
http://wordpress.org/extend/plugins/custom-content-type-manager/

Posts

http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress
http://devpress.com/blog/conditional-checks-for-custom-post-types/
http://css-tricks.com/forums/discussion/8538/wordpress-3.0-custom-post-types-and-meta-boxes/

Easy meta boxes with WPAlchemy

WPAlchemy MetaBox PHP Class

The slides

 

Proper float clearing

I was browsing through Forrst recently and happened across the following advice on float clearing.

An easy way to properly clear floats without extra markup. If you’re not using some sort of clearfix you probably should be.

.clearself:before,
.clearself:after {
content: " ";
display: block;
height: 0;
overflow: hidden;
}
.clearself:after {clear: both;}
.clearself {zoom: 1;} /* IE < 8 */

This looks like a great way of reducing design related markup in your HTML. What do you think? Have you tried this technique before?

The original post is here.

HTML Fractions

I wanted to use some pretty fractions in an article today. I don’t like the look of “1 1/2”, not very elegant.

Of course, the answer lies within HTML special characters. There are a few ways to achieve the same thing:

  • &frac14; will give you ¼. You can change the ‘1’ and ‘4’ to any other number. But hang on, what would &frac124; give you? The answer is ½4;. Hmm…
  • The more versatile solution is to use &frasl;. However, this won’t format properly without adding <sub> and <sup> like:

    <sup>1</sup>&frasl;<sub>10</sub>

    Which will output 110.

Boom! HTML fractions!