Close

A client recently approached me looking to build a custom plugin to integrate LightSpeedEVO with WooCommerce. The plugin need to perform the following functions:

  • Pull inventory from LightSpeedEVO into WooCommerce.
  • Synchronize all inventory data, including pricing, images, product descriptions, etc.
  • Perform regular checks against LightSpeedEVO to keep inventory on the WordPress / WooCommerce website up to date.
  • Remove products from WooCommerce when they are sold or removed in LightSpeedEVO.

The plugin was built over a period of weeks and is currently live and functioning on our clients website.

Given the nature of the integration, we cannot simply package and sell the plugin at this point, however, we can offer custom integrations with LightSpeedEVO for your website now, using the plugin we developed as the base.

Contact us today if you are interested!

Recently I was tasked with enabling Schema for a client website which utilized Yoast SEO.

Initially it seemed like an easy request as Yoast SEO does support schema out of the box, however things weren’t quite as easy as I initially thought they would be.

Yoast SEO offers wide range of Schema confirguration options under the “Search Appearence” section of its options panel. Furthermore, it allows you to customize schema on a post by post basis too.

However, I found that when changing the schema for one of my post types to “NewsArticle” or “Article”, the posts were still loading with the “WebPage” schema type. No matter what settings I chose, Yoast SEO refused to use my schema settings for any custom post type.

I turned to the internet, hoping to find a solution but all I could find were some obscure references from the Yoast support team to the following page: https://developer.yoast.com/features/schema/api/

This page included mention of the following filter:

wpseo_schema_article_post_types

The only notation for this filter though is:

allows changing for which post types we output the Article graph piece.

With little else to go on, I turned back to the internet and found some references from fellow users and developers:

Some useful information was included here, including a function to try and adjust the WebPage Schema to Article:

// use schema type article
function schema_article_post_types($post_types) {
	$post_types = array('my-post-type', 'my-other-post-type', 'post');
	return $post_types;
}
add_filter( 'wpseo_schema_article_post_types', 'schema_article_post_types' );

This function did not get it working for me at all, even though it should have. In fact, a GitHub bug report was opened for this issue and one of the plugin developers suggested using code just like this: https://github.com/Yoast/wordpress-seo/issues/12674

As of February 26th 2021, this issue is still unresolved even though the ticket on Git itself has been closed. In the end, I ended up using the following code to disable Yoast Schema completely:

add_filter( 'wpseo_json_ld_output', '__return_false' );

I then manually coded schema into my clients theme. This may not be the easiest option for some, so I can also recommend “Schema & Structured Data for WP & AMP” from the WordPress Plugin Repository, which I have tested and appears to work very well!

Experiencing this bug too? Did you find a solution?

Let me know below!

Most themes these days include an options panel where you can change various aspects of your theme such as colors, font family, font size, et cetera.

There are many different ways of building an options panel to include with your theme, though my preferred method is via Advanced Custom Fields Pro.

Regardless of your method though, typically you retrieve settings from your options panel in PHP. For example, in Advanced Custom Fields you would get an option like this:

<?php $option_value = get_field('field_name', 'options'); ?>

To utilize this value in your CSS, you’d typically have to use inline CSS or pull in this CSS via a PHP file and then enqueue that PHP file in your site header.

This is not a particularly efficient method as it typically prevents site optimizers like WP-Rocket or W3 Total Cache from caching that CSS.

Generating a CSS file from a PHP file

Create a PHP file containing your dynamic CSS the way you typically would. For example:

$option_value = get_field('field_name', 'options');

echo '<style>
.primary-color{
	color:'.$option_value.';
}
</style>';

I typically call this file something like dynamic.css.php but you can call it whatever you want.

Adding the following code in your theme functions.php file will grab the CSS from this file and dump it into a new .css file:

add_action('parse_request', 'parse_dynamic_css_request');
function parse_dynamic_css_request($wp) {
	$ss_dir = get_stylesheet_directory(); // Shorten code, save 1 call
	ob_start(); // Capture all output (output buffering)
	require($ss_dir . '/css/dynamic.css.php'); // Generate CSS
	$css = ob_get_clean(); // Get generated CSS (output buffering)
	file_put_contents($ss_dir . '/css/static.css', $css, LOCK_EX); // Save it
}

I’d added commenting into the above function to explain what each part does.

It generates a file called “static.css” which you can then enqueue in your theme header:

wp_enqueue_style('your_dynamic_style', get_template_directory_uri().'/css/static.css');

By generating a static CSS file from your dynamic options, you can allow your users to be able to change various styling options on their website such as background colors, font colors, padding and margins, font sizes and more without taking a huge performance hit by having to inline all of this dynamically generated CSS.

This can be important when speed is an emphasis and you want to cache as much of your CSS as possible. Popular performance tests such as PageSpeed Insights often penalize websites with a lot of inline CSS, so this can also help boost your scores!

Questions or Comments?

Let me know below!

The repeater field in Advanced Custom Fields is one of the most powerful fields available, allowing you to easily build out entire blocks of content with just a single block of code inserted into your theme.

But what if you want to alter your code output in specific situations such as when a certain number of rows are present, or for a specific row?

Output for a Specific Row

Altering the output for a specific row is pretty easy.

Here is what standard code for your repeater might look like – this example is taken directly from

if(have_rows('repeater_field_name')): while (have_rows('repeater_field_name')) : the_row();
	the_sub_field('sub_field_name');
endwhile;

Adding a counter is pretty easy:

$counter = 0;
if(have_rows('repeater_field_name')): while (have_rows('repeater_field_name')) : the_row();
	the_sub_field('sub_field_name');
	$counter++;
endwhile;

This inserts a counter and increases it by one every time the repeater loops, thereby allowing you to have a specific output for specific iterations:

$counter = 0;
if(have_rows('repeater_field_name')): while (have_rows('repeater_field_name')) : the_row();
	if($counter == 2){
		the_sub_field('another_sub_field');
	}
	the_sub_field('sub_field_name');
	$counter++;
endwhile;

This loop inserts an additional subfield output only for the third iteration of the repeater loop.

In this way, you can alter output for specific repeater items.

What if I want to update the code based on the total number of repeater items?

You can also count the total number of iterations and alter the output code.

Imagine a scenario where you want to output content from the repeater into columns that span the full width of a page. You won’t necessarily know in advance how many repeater elements might be added so therefore, you won’t know how many columns you need.

The first thing you need to do is to count the total number of rows:

$total_rows = count(get_field('repeater_field_name'));

Once you have the total number of rows, altering the output is a simple if/else query:

if($total_rows == ('2' || '3'|| '4')){
	// Upto 4 columns
	echo '<div class="columns three">';
} elseif ($total_rows == ('5' || '6')){
	// 5 or 6 columns
	echo '<div class="columns two">';
} elseif ($total_rows >= 7){
	// Greater than 7 columns
	echo '<div class="columns one">';
}

Using this code, you can build layouts that dynamically update based on the number of rows a user has entered.

Questions? Comments?

Let me know below in the comments.

As many of you probably know, WP Engine implements some very aggressive caching which can have some impressive effects on page speed and search ranking.

However, it also causes some side effects like making determining a user’s location programmatically very difficult.

I recently tackled this issue when writing a plugin that makes some use of geo-location to limit content visibility. Because I wanted to code to be versatile and work on or off WP Engine, I had to come up with a method of doing so.

This is what I eventually came up with:

function get_visitor_country() {
    // We need custom code to accommodate for WP Engines aggressive caching, therefore we need to use WP Engine GeoTarget on WP Engine. This provides future proofing if the host is ever changed.

    $wpe_getuser_country = getenv('HTTP_GEOIP_COUNTRY_CODE'); // This is unique to WPE Engine, so if it returns a value we can assume we're on WP Engine and if nothing is returned, then we're not.

    if($wpe_getuser_country != ''){

        $user_country = $wpe_getuser_country;

    } else {

        $ipaddress = '';
        if (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ipaddress .= $_SERVER['HTTP_CLIENT_IP'] . ' - ';
        }
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ipaddress .= $_SERVER['HTTP_X_FORWARDED_FOR']. ' - ';
        }
        if(isset($_SERVER['HTTP_X_FORWARDED'])) {
            $ipaddress .= $_SERVER['HTTP_X_FORWARDED']. ' - ';
        }
        if(isset($_SERVER['HTTP_FORWARDED_FOR'])) {
            $ipaddress .= $_SERVER['HTTP_FORWARDED_FOR']. ' - ';
        }
        if(isset($_SERVER['HTTP_FORWARDED'])) {
            $ipaddress .= $_SERVER['HTTP_FORWARDED']. ' - ';
        }
        if(isset($_SERVER['REMOTE_ADDR'])) {
            $ipaddress .= $_SERVER['REMOTE_ADDR']. ' - ';
        }
        if($ipaddress == '') {
            $ipaddress = 'UNKNOWN';
        }   

        if($ipaddress == 'UNKNOWN'){
            $user_ip = '';
        } else {
            $user_ip = $ipaddress;
        }
        $countryArray = json_decode(file_get_contents('http://www.geoplugin.net/json.gp?ip='.$user_ip));
        $user_country = $countryArray->geoplugin_countryName.'!';

    }

    return $user_country;

}

$final_user_country = get_visitor_country();

This is environmentally aware, meaning if you utilize it on a website that is hosted with WP-Engine and later move that website to another host, your geo-targeted content will continue to function.

Questions? Comments?

Let me know below in the comments.

I recently needed to dynamically insert a menu item into a specific menu programmatically.

Almost every solution out there required targetting the menu by its menu location however my menu was not assigned a menu location under “Appearance > Menus” and I wanted to find a way to target the menu by its slug or menu ID.

The information was out there to find but not particularly well documented so I figured I’d share my eventual solution:

add_filter('wp_nav_menu_items','custom_menu_item', 10, 2);
function custom_menu_item($menu, $args){
	if($args->menu == '64849'):
		return $menu."<li><a href="#">My Menu Item</a></li>";
	endif;
    return $menu;
}

This function, inserted into my theme function.php file allows me to target my specific menu ID (64849) and then append an item into the end of the menu.

While achieving my basic goal, I realized that if a situation arose where I needed to insert an item in a specific position, this code wouldn’t work.

What if I need to insert a menu item at the start of the menu? Or in a specific position?

Accomplishing this is a little more complicated but I did eventually solve the problem.

I built a function to capture menu items into an array, then utilizing an array_splice to insert our menu item.

Utilizing an array_splice allows us to insert an item into the array at any position so it gives us the control we need to insert a menu item wherever we want:

function insert_menu_item($items, $args){
	// Target menu by ID
	if($args->menu == '64849'){
		// Build empty array
		$items_array = array();
		while(false !== ($item_pos = strpos($items, '<li', 3))){
			// Insert existing menu items into array
			$items_array[] = substr($items, 0, $item_pos);
			$items = substr($items, $item_pos);
		}
		$items_array[] = $items;
		// Utilize array splice to insert our menu item at position 0
		array_splice($items_array, 0, 0, '<li><a href="#">My Menu Item</a></li>');
		$items = implode('', $items_array);
    }
    return $items;
}
add_filter('wp_nav_menu_items', 'insert_menu_item', 10, 2);

The second argument value on the array_splice dictates the position to insert our menu item, so for example, changing the array_splice as follows would insert our custom menu item after the second item:

array_splice($items_array, 0, 2, '<li><a href="#">My Menu Item</a></li>');

In this way, you can inject a menu item as any position into a specific menu ID.

Questions? Comments?

Let me know below in the comments.