Category: Code

Simple Canonical Redirect for WooCommerce

If your Woocommerce products are within multiple categories or hierarchies they will have multiple potential URLS. I always find this annoying. If you also find it odd that the URL displayed in the post edit screen under the Title box, which is named “permalink” is not automatically the go-to URL you might wish to utilise the following code to fix this with a 301 redirect.

Example:

 

website.com/scotland/glenelg-skye-ferry

would now redirect to the (correct) Permalink url:

website.com/travel/scotland/glenelg-skye-ferry

The code:

add_action('template_redirect', 'redirect_to_canonical_url');
function redirect_to_canonical_url() {
if (is_singular('product')) {
global $post;

// Get the canonical URL for the current product
$canonical_url = get_permalink($post->ID);

// Get the current URL
$current_url = (is_ssl() ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

// Normalize URLs to avoid issues with trailing slashes, query strings, etc.
$canonical_url = trailingslashit($canonical_url);
$current_url = trailingslashit(preg_replace('/\?.*/', '', $current_url)); // Strip query string

// Compare and redirect if necessary
if ($current_url !== $canonical_url) {
wp_redirect($canonical_url, 301);
exit;
}
}
}

WooCommerce | Same Product Base & Shop Base

Here is a simple* code, modified after the solution by Le Van Toan outlined on his blog based in Vietnam. Have you ever tried to setup your own custom permalinks in WooCommerce so that the product base and the shop base are one and the same? This plugin makes it so.

Desired WooCommerce Shop/Products base structure:

shop page – website.com/shop/
product parent category archive page – website.com/shop/parent-category-slug/
product child category archive page – website.com/shop/parent-category-slug/child-category-slug/
single product page – website.com/shop/parent-category-slug/child-category-slug/single-product-page-slug

Here is what you need to set in Settings > Permalinks
visit website.com/wp-admin/options-permalink.php

Optional > Product category base: shop
Product permalinks > Custom base: /shop/%product_cat%/

Here is the code, for your functions.php

function category_base_is_shop_base(){
// Get all product categories
$terms = get_terms(array(
'taxonomy' => 'product_cat',
'post_type' => 'product',
'hide_empty' => false,
));

// Check if terms are retrieved successfully
if ($terms && !is_wp_error($terms)) {
$siteurl = esc_url(home_url('/'));
// Loop through each term to set up custom rewrite rules
foreach ($terms as $term) {
$term_slug = sanitize_title($term->slug);
$baseterm = str_replace($siteurl, '', get_term_link($term->term_id, 'product_cat'));
// Add rewrite rules for base term, pagination, and feeds
add_rewrite_rule($baseterm . '?$', 'index.php?product_cat=' . $term_slug, 'top');
add_rewrite_rule($baseterm . 'page/([0-9]{1,})/?$', 'index.php?product_cat=' . $term_slug . '&paged=$matches[1]', 'top');
// add_rewrite_rule($baseterm . '(?:feed/)?(feed|rdf|rss|rss2|atom)/?$', 'index.php?product_cat=' . $term_slug . '&feed=$matches[1]', 'top');
}
}
}

// Hook into 'init' action to set up rewrite rules
add_action('init', 'category_base_is_shop_base');

// Function to run when a new term is created
add_action('create_term', 'category_base_is_shop_base_edit_success', 10, 2);

function category_base_is_shop_base_edit_success($term_id, $taxonomy) {
category_base_is_shop_base();
// Inform the user to flush permalinks manually
add_action('admin_notices', function() {
echo '<div class="notice notice-warning is-dismissible"><p>To ensure your custom permalink structure works, flush your permalinks by going to Settings > Permalinks and clicking "Save Changes".</p></div>';
});
}

Visit your Settings > Permalinks and hit save twice to force flush/rebuilding of permalinks. Done.

“Masonry for Bricks Product Elements” – WordPress Plugin

Here’s a plugin I have written that extends the Bricks theme, specifically it allows you to use Masonry.js (built into WordPress) with the Product Element. I was surprised this wasn’t a built-in option and created this lightweight plugin to achieve integration. All you need to do is install the plugin and add a custom id to the product element.

The plugin is straightforward enough, you will find a settings panel where you may customise the style sheet. It is important you add the id `#masonry-for-bricks` to the relevant product element via the Bricks builder for the masonry effect to work.

Masonry for Bricks Product Elements – Download Plugin 1.1

(more…)

Give WordPress Media Thumbnails Their Own Directory

If, like me, you find WordPress incredibly messy in the way it fills up your media folder with a noise of rebuilt thumbnails here is a little code for your functions.php

It will create future thumbnails in their own /thumbnails/ directory within your media folder.

function custom_thumbnail_save_directory($metadata, $attachment_id) {
$custom_subdir = '/thumbnails/';

$upload_dir = wp_upload_dir();
$custom_dir = $upload_dir['basedir'] . $custom_subdir;

if (!file_exists($custom_dir)) {
mkdir($custom_dir, 0755, true);
}

if (!empty($metadata['sizes'])) {
foreach ($metadata['sizes'] as $size => $size_info) {
$source_file = $upload_dir['path'] . '/' . $size_info['file'];
$destination_file = $custom_dir . '/' . $size_info['file'];

if (file_exists($source_file)) {
rename($source_file, $destination_file);
}

$metadata['sizes'][$size]['file'] = 'thumbnails/' . $size_info['file'];
}
}

return $metadata;
}
add_filter('wp_generate_attachment_metadata', 'custom_thumbnail_save_directory', 10, 2);

function custom_thumbnail_directory($uploads) {
$custom_subdir = '/thumbnails/';

if (!file_exists($uploads['basedir'] . $custom_subdir)) {
mkdir($uploads['basedir'] . $custom_subdir, 0755, true);
}

return $uploads;
}
add_filter('upload_dir', 'custom_thumbnail_directory');

Use a plugin to rebuild your thumbs after adding this code. Now, isn’t that tidy?

Bulk Rename on SSH (FTP)

Really simple one, I need to bulk ‘find and replace’ a number of files within a folder, SSH connection with Terminal.app on OSX.

Example below searches for ‘that’ and replaces all instances with ‘this’.

for file in file_is_something_like_that*.jpg; do
mv "$file" "${file//that/this}"
done

Run that command and immediately the files are renamed.

Google Product Feed : Featured

Here’s a script for ‘Google Product Feed‘ by Ademti Software which allows you to subdivide a large feed (for later use in Google Ads) by the ‘featured’ option in Woocommerce. If the product is ‘featured’ then ‘custom_label_0’ will be populated with: ‘featured’. I thought it was worth sharing.

function lw_woocommerce_gpf_edit_custom_label_featured( $elements, $product_id, $variation_id = null ) {
if ( ! is_null( $variation_id ) ) {
$id = $variation_id;
} else {
$id = $product_id;
}
$featured_product_ids = wc_get_featured_product_ids();
if ( in_array( $id, $featured_product_ids ) ) {
$elements['custom_label_0'] = array( 'featured' );
} else {
$elements['custom_label_0'] = array( 'not_featured' );
}
return $elements;
}
add_filter( 'woocommerce_gpf_elements', 'lw_woocommerce_gpf_edit_custom_label_featured', 11, 3 );

Drop-Print.com } Update Etsy from CSV

Today, I want to introduce a nifty tool that’s been a game-changer for my Etsy shop: Drop-Edit. Picture this: managing your Etsy listings as effortlessly as tweaking a spreadsheet. That’s the magic of Drop-Edit. With just a CSV file, I can now oversee hundreds, theoretically thousands, of listings in my Etsy Shop. It’s like having a command center where I can tweak details, bulk edit, upload images, or switch up tags. It now handles bulk editing Etsy Listings for digital downloads.

The process is straightforward and efficient – a simple ‘Update on Etsy’ button links the tool to the Etsy API and, bingo, with my permission, it syncs with my Etsy shop. The instant updates are a huge time-saver.

And there’s more! This weekend, Drop-Edit (which is a subscription service) rolled out a brilliant new feature. Not only does it support Etsy>CSV, which is a lifesaver in itself, but now it also allows for bulk updating of digital downloads. Imagine the hassle saved! I managed to create and organize over 200 digital download listings on Etsy, seamlessly placing each digital item in its listing. Without Drop-Edit, this would have been a Herculean task, devouring time and patience.

Drop-Edit: drop-print.com/etsy/

(more…)

Move WordPress Uploads Out of WordPress Directory

Here’s a simple one (which took me many hours to correctly configure). This little script, inserted into a custom plugin or functions.php in a child-theme will allow you to move your uploads folder out of the WordPress directory. Keeps things neat and tidy for my purposes.

Currently I have wordpress in its own directory, ie. website.com/wordpress/

Now assume publicly facing url is website.com, that makes my uploads website.com/wordpress/wp-content/uploads – a terribly unprofessional looking URL.

With this code you can move the uploads directory to the top folder. Be sure to move the files, or use Better Search and Replace to change your DB if required.

add_filter(
'upload_dir',
function ($dirs) {
$new_upload_dir = '/home/domains/website.com/public_html/uploads';
$new_baseurl = 'https://website.com/uploads';
$dirs['path'] = $new_upload_dir . $dirs['subdir'];
$dirs['basedir'] = $new_upload_dir;
$dirs['baseurl'] = $new_baseurl;
$dirs['url'] = $new_baseurl;
return $dirs;
},
15 // default is usually 10
);

Note: you’ll need to work out where ‘$new_upload_dir’ with some detective work of your own. Good luck!

Filter Insta Results by tag w/ Social Feed Gallery

Occasionally I build websites for folks. Recently I’ve been replacing stale old static galleries with a slim WordPress plugin that sync’s a users’ feed to a local cache and formats it in a nice way for the visitor. Its easier to update for the client (if they have a smartphone) and the visitor doesn’t need to be ab Instagram user or have any knowledge of that site to view.

The plugin I use is Social Feed Gallery by Quadlayers. It breaks less than other plugins I’ve used in the past, most of the time it isn’t their fault. Instagram’s API seems to chop-and-change.

Anyway- this isn’t an advert. If you want to display a selection of your Instagram images on your WordPress website but you’d like to filter out certain images (I do this by way of a hashtag #nosync ) then add this script to your CSS:

[data-item*="no-sync"] {display: none!important;}

Remember to tag the relevant items #no-sync, then hit the ‘Cache’ refresh button in your Social Feed Gallery dashboard panel. As Steve would have said *boom*. Discovered this solution at Stack Exchange, full of helpful humans who still beat AI!

FTP Transfer using SSH

Yesterday I learned how to migrate to a new web host in a very satisfyingly geeky way. If you are on Mac OS open up Terminal (enable the Homebrew theme) dim the lights, or block them out if possible, stick on the Matrix Soundtrack from 1998 and prepare to login to SSH! Its command line and slightly overwhelming.

SSH gives a user access to a remote machine so you can run commands on that server… as if you were in the room. Like scren sharing in the command line. When migrating loads of files from one remote place to another this is great as it saves us a step. Rather than transferring gigabytes of data from one remote server to our local machine to then forward on to another remote machine we just login and get the two remote machines to sort it out between themselves. Up here in the Scottish Highlands I’m on a community owned broadband network and I’m almost certain our local internet guru would have something to say about 100’s of gigabytes flying around so that was my reason for stumbling upon this magic code.
(more…)