The how to include the SKU into WooCommerce product permalinks!

It has taken a while but I finally managed to get it working… the SKU from a WooCommerce product in the permalink. Yes!

Now we can finally make WooCommerce product permalinks like: http://domain.tld/product-base/sku/product-name

After some Googling I ended up at this excellent starting point: How to add sku to product url in woocommerce? 

It was quickly modified to have the SKU not added to the end of the permalink like a name reference (#SKU) but to be an integrated part of the permalink.

// place this code in your (child) themes function.php
function jpb_custom_meta_permalink( $link, $post ){
$post_meta = get_post_meta( $post->ID, '_sku', true );

if( empty( $post_meta ) || !is_string( $post_meta ) ) {
$post_meta = 'sku_missing';
}

$link = str_replace( '%%sku%%', $post_meta, $link );
return $link;
}
add_filter( 'post_link', 'jpb_custom_meta_permalink', 10, 2 );

function append_sku_string( $link, $post ) {
$post_meta = get_post_meta( $post->ID, '_sku', true );

if ( 'product' == get_post_type( $post ) ) {
//$link = $link . '#' .$post_meta;
$link = str_replace( '%%sku%%', $post_meta, $link ); // go to the WordPress Permalink settings page to set the Custom Product Permalink Base to: /product-base/%%sku%%
return $link;
}
}
add_filter( 'post_type_link', 'append_sku_string', 1, 2 );

After setting the custom permalink structure for products with /product-base/%%sku%%, the permalinks worked BUT I couldn’t load the product pages… oops! So time for troubleshooting. As I fairly quickly thought into the direction of RewriteRules in the .htaccess file I’ve been looking into that but they are absolutely not my favorite thing to deal with so progress was slow. That said – the solution is the following:

# BEGIN WC SKU post meta in permalink (note: requires code in functions.php as well)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^product-base/([A-Za-z0-9-_]+)/([A-Za-z0-9-_]+)/?$ ?sku=$1&product=$2 [NC,L]
</IfModule>
# END WC SKU post meta in permalink

Just make sure that you place this above the # BEGIN WordPress line in your .htaccess and you’re ready to rock’n’roll. Yeah baby!

Some notes:

  • The WC SKU is a post meta named _sku.
  • There is no support in the WordPress core for post meta values in permalinks.
  • You can name the product-base anything you want as long as you change it in all the code and also on use it on the WordPress > Settings > Permalinks page.
  • In the RewriteRule the sku=$1 can also be removed as WordPress will not look at it to locate and load your product page, without the product=$2 you will just get an 404 error!
  • it would probably have been better to use ?_sku but it doesn’t matter, as explained in the previous bullet, it’s just there for the show.
  • The RewriteRule could also have been placed within the #BEGIN WordPress … #END WordPress section of your .htaccess as long as it’s placed between RewriteRule ^index\.php$ – [L] and RewriteCond %{REQUEST_FILENAME} !-f. To make it more fool proof -for myself- I just go for a separate section above the WordPress generated code.
  • It would be really great if the SKU would become part of the permalink options directly via the WooCommerce plugin so we don’t have to play around with these extra lines of code in our functions.php and .htaccess. So please request this feature with the WooCommerce team as well. It’s also the reason why I have chosen to use %%sku%% instead of %sku%, just to point out to myself it’s not a core functionality ;)

 

Aside

Jottacloud – Dropbox like service out of Norway

I was just wondering if there are good non-US alternatives for services like Dropbox and found one in Norway which looks and works great. As good as the same functionality as Dropbox and fast when synchronizing . Great stuff – my account is here to stay and I already moved some of my Dropbox data towards Jottacloud and more will follow soon!

Free accounts come with 5GB but when you use this referrer – you’ll get another 5GB as bonus. So head over to Jottacloud via  and get your free 10GB account today!

WP snippet: restrict gallery access – with override

Galleries are great but sometimes you just want to keep your photo’s private to just a limited group unless you choose to share them with the entire internet community. This WordPress snippet will help you by restricting the ability to view your galleries by default.

To see the galleries you must be (1) logged in and (2) assigned to an user role with the ‘view_gallery’* capability granted. You can also make a specific gallery (or better, all galleries in a specific post) accessible to anyone by simply adding the override tag ‘public gallery’ to the post.

* You’ll need to add this custom capability to your WordPress installation with the help of, for example, the Members or the User Role Editor plugin. I did also create a clone of the Subscriber user role and called it Subscriber Plus and granted that one new role and the higher user roles with the ‘view_gallery’ capability so whenever someone registers he/she still need to be assigned to an appropriate user role. This is to allow anyone to register to your side but still gives you control over who is entitled to see the galleries and who’s not.

// paste the code in the functions.php of your (child) theme
// source: https://golabs.nl/wp-snippet-restrict-gallery-access-with-override/

// only run this code when showing the front-end
if( !is_admin() ) {
  // replace the original gallery shortcode on init
  add_action( 'init', 'update_gallery_shortcode');

  function update_gallery_shortcode() {
    remove_shortcode('gallery', 'gallery_shortcode');
    add_shortcode('gallery', 'gallery_shortcode_enhanced');
  }

  function gallery_shortcode_enhanced( $atts ){
    // the need for the user being logged in and having the view_gallery capability assigned to his/her user role
    // can be overridden by adding the 'public gallery' tag to the post!!
    if( ( is_user_logged_in() && current_user_can('view_gallery') ) || has_tag( "public gallery" ) ) {
      // user is logged in and has the view_gallery capability assigned to his/her user role...
      // OR we are allowing access to anyone in case it's tagged as a 'public gallery'...
      // cool, let's show the gallery
      echo gallery_shortcode( $atts );
    } else {
      // oh no, this user is not allowed to see the gallery, let's see what the reason is...
      if( !is_user_logged_in() ) {
        // not logged in, then offer the login form
        echo "<p>Viewing the gallery is restricted to logged in users only.</p>";
        echo wp_login_form();
      } else {
        // logged in BUT the view_gallery capability is not assigned to the user role
        echo "<p>Humm... it appears that you're assigned user role is missing the rights to view the gallery.
        Please ask the admin if you're entitled to an user role upgrade so you can see the galleries as well.</p>";
      }
    }
  }
}

Suggestions to improve / extend the snippet are always welcome and can be posted as a comment below or send via the contact form.

Footnote: disabling your (child) theme will make all galleries visible to anyone again. Therefor I’ll turn this into a plugin shortly as well. Stay tuned!