Manipulating WordPress Canonical URLs

For many people, it’s not necessarily a big deal to move a blog from one domain to another, and losing social sharing metrics as a result (at least when you’re like me, and most shares are single digits, anyway). This commonly happens because the share counts get tied to each unique URL. If that changes, then so does the count. Virtually every social platform, however, allows you to specify the URL that’s used when sharing via special <meta> tags. This whole issue becomes much more important, though, when you’re a company with many hours and lots of marketing dollars vested in social metrics and the value they drive to your business.

Recently, I ran into an issue where we were combining a Drupal base site with a WordPress blog into one site. The challenge created was that the blog had thousands of shares on posts, and they didn’t want to lose that data because the blog now lives on the base site instead of apart from it. Probably the most obvious, and simplest solution would be a multisite WordPress install. However, we stepped in later in the process after the new site had been developed, and instead had to retrofit the patches. Converting over to multisite would have taken a lot of time and extra QA work. (Note: in the long run, this might still happen, as it is a more fitting solution given the problem we’re talking about.)

First thing, we were lucky that the base blog post slugs didn’t change, so no need for clever htaccess rewriting or anything like that, which you could do (or just go back to the original permalink structure, which is the easiest path unless you have a specific reason to not use it). We also CNAME’d the old blog domain to the base site, so that it worked either way. Using a load balancer rule (or you could do it in htaccess), we made sure any request to a blog post using the root domain would get 301’d to the blog CNAME entry. That covered the basic issue of ensuring the blog used the old URL scheme.

By and large, this should take care of accessing the blog posts via its original domain, even though they are part of the base WordPress install. You might also have to make tweaks to your theme where you link posts as well, but that totally depends. For instance, if there’s a feed of blog posts on your home page, you’ll need to be sure you account for the desired URL, because if you let WordPress handle it automatically, it’ll use the home_url() value for the links. This should still work, and would get caught by your 301 if you configured one, but it could be a slightly undesirable UX scenario for users to see one URL in a link, and end up at a different one.

This leaves one more piece of the puzzle. If you’re using Yoast SEO or other sharing tools, most of those use get_permalink() to set their sharing URL, which means they’ll have the wrong, base domain as the URL for the blog posts. Luckily, Yoast has a filter for just this issue called wpseo_canonical(). Here’s an example of how to use that filter, which will set a <link rel="canonical">, along with several Open Graph and social specific URL meta tags. Just stick this, customized to your specific needs, into your theme’s functions.php file:

Add to functions.php

PHP

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

// SET UP PROPER CANONICAL URLS FOR YOAST

functionblog_canonical($canonical){

// PASS IN OUR POST OBJECT BECAUSE WE NEED IT

global$post;

// CHECK FOR BLOG POSTS (COULD DO THIS FOR ANY TYPE THOUGH)

if(is_single()){

// ASSUMES THE BASE SLUG DIDN'T CHANGE, BUT YOU NEED TO ASSOCIATE ONE DOMAIN WITH ANOTHER

// RUN THE FILTER ON PAGES. NORMAL PAGES GET A NORMAL CANONICAL REFERENCE, BLOG POSTS GET THE REMAPPED ONE

add_filter('wpseo_canonical','blog_canonical');

Without this, even with all the other work, you’d end up with something like <link rel="canonical" href="http://your-base-domain.com/2015/08/blog-slug"> instead of <link rel="canonical" href="http://your-other-domain.com/2015/08/blog-slug">. This could still cause both search engines to look at your blog screwy, and mess with the share counts, that’s the reason for that. I also had to manually modify one of the plugins we use with similar logic, because they didn’t offer the ability to override the URL format used, but that just depends on what plugins you have running where, and you’ll have to adapt accordingly. In this case though, the Yoast filter will address most of the issue to make sure your blog posts properly reference their original URLs within social metric APIs, and work via them.

But, with Yoast, some quick code, and a little 301 safety net, you should be able to ensure that moving the blog to a new site doesn’t throw all your metrics out the window.

ASIDE: If you’re trying to maintain a similar kind of faux-bifurcated site setup, it probably bears mentioning that similar attention will probably need to be paid to how you embed your analytics tracking on the site, whether you want the blog tracked separately or as part of the overall site. Lots of fallout to consider in this kind of setup.