ShopWP Admin Settings

Custom WordPress Admin Settings Using Gutenberg

Iain Poulson over at Delicious Brains recently wrote an article entitled, 5 Ways to Create a WordPress Plugin Settings Page. It’s an excellent breakdown of different approaches that developers can take when building settings pages for WordPress plugins.

Iain’s article inspired me to share my own approach to this process since it has changed quite a bit. Let’s dive in and take a look!

My Plugin Philosophy

As a WordPress developer, I’ve come to the conclusion that Gutenberg isn’t going anywhere. Say what you will about Classic Editor, or ClassicPress—the future of WordPress is undeniably, Gutenberg. Personally, I love that tools like ClassicPress and Classic Editor exist. They’re fantastic, and kudos to the people who made them! 👏

At the same time, as a plugin developer (and ultimately business owner), I want to make sure that my product is adapting to the latest technologies. More importantly, I want to make sure my plugin follows the “WordPress way” of doing things. I think this is important for giving users a “familiar experience” to what Core provides by default. I don’t want my users to context switch when using my product—whether visually or functionally.

So what does this mean for building admin settings pages?

The React Way

As Iain mentions in his article, The WordPress world has adopted React as a base technology in core. Just like they did with jQuery so many years ago. With each core update, React serves more and more as the foundation for everything UI related.

So, I’m also building my admin settings in React now 😀

I’d like to walk through how I’m doing this for the rest of the article. I’m going to assume that you’re familiar with React. However if you use Vue or Angular instead, the examples I’m showing here should at least make conceptual sense.

Let’s go!

Setting things up

Before I can begin building the React app for the settings, I need to get the actual admin page working. I usually do this using code similar to this:

function plugin_admin_page() {
   include_once WP_SHOPIFY_PLUGIN_DIR_PATH . 'admin/partials/wps-admin-display.php';

function add_dashboard_menus() {
   add_menu_page('ShopWP', 'ShopWP', 'manage_options', 'wpshopify', 'plugin_admin_page', $icon, null);
   add_submenu_page('wpshopify', 'Settings', 'Settings', 'manage_options', 'wps-settings', 'plugin_admin_page');

add_action('admin_menu', 'add_dashboard_menus');

In case you’re unfamiliar with what’s going on, the above code will basically add a new Menu item to WordPress for our plugin. We’re then telling WordPress to load the wps-admin-display.php file when the user opens our newly created settings page.

After adding this to our plugin, we’ll be presented with a blank page that looks something like this. The reason it’s blank is because we’re also assuming that we haven’t added anything to wps-admin-display.php yet.

An example of a black WordPress settings screen

Note: I’m intentionally being sparse in details of this process as the main purpose of the article will be to focus on the React side of things. For a more detailed explanation have a look at Iain’s article.

Adding the Entry Point

Now that the settings page is working we need to add our “entry point” for our React app. We can do this by adding the below HTML into the wps-admin-display.php file.

<div id="wpshopify-app-settings"></div>

Ok, now the fun begins.

How WordPress Manages Components

As I mentioned earlier, the wonderful people behind WordPress have open-sourced many of the core components used in Gutenberg. This includes simple things like input fields, spinners, color swatches, etc. Developers can then pull these components into their own projects. Awesome right? 😎

This brings me to a larger point: we as developers now have a way of reusing core components that are proven to work. We no longer have to reinvent text fields, loading spinners, or write custom CSS to “match” what core displays.

This is huge! Not only for productivity but for overall code quality and maintenance.

So where do you find these components? You can find a full list here.

Screenshot of the WordPress documentation site

Using the Components

There are currently two ways to consume these components in your own project. You can either use the npm package @wordpress/components , or rely on the global wp.components variable. There are pros and cons to each.

One of the benefits of using the @wordpress/components package directly is that you’ll have access to some components that haven’t been pushed to core yet. For example, the Card and CardHeader components.

Another benefit is that you can start using these components now, even if you have to support users who are using WordPress below version 5.0.

A benefit to using the built-in wp.components variable is that you won’t need to bundle and ship the components library in your plugin or theme. This can potentially be a huge savings in asset size because you can also exclude React and ReactDOM from your bundle. However this assumes you’re only supporting WordPress 5.0 +.

At the end of the day the decision will be up to you, but here is an example of how to load the Spinner component using both approaches:

Using @wordpress/components:

import { Spinner } from '@wordpress/components';

Using wp.components

const { Spinner } = wp.components;

Both of these approaches will produce the following:

The Native Approach: Requiring Dependencies

Building on the above <Spinner> component example, if you decide to use wp.components there is one additional step that needs to be taken before this will work.

While WordPress will allow you to use these components, you must first tell WordPress that your plugin depends on them. You can do this by adding wp.components to the dependency array when you enqueue your styles and scripts. Here’s an example:

Enqueue styles:

wp_enqueue_style('my-styles', 'dist/admin.min.css', ['wp-components']);

Enqueue scripts

wp_enqueue_script('my-scripts', 'dist/admin.min.js', ['wp-element', 'wp-components'], '', true);

Notice here that we’re also adding wp-element to our scripts. This is to ensure that WordPress loads React under the wp.element variable.

Managing Settings Data

I thought I would touch quickly on this part of the process because it has changed quite drastically as well.

In my prior approach, I would lean heavily on accessing the settings data within PHP. For example, before including my settings page I would fetch all the settings data from the database. Then I would set the HTML form inputs with the data. This works of course, but it is not the way I’m doing things now.

Because I’m rendering the form inputs on the client-side, I need a way to pass the state of the current settings into the React app on each page load. I’m doing this through the wp_add_inline_script function.

public function stringify_settings($settings) {
   return "const wpshopify = " . wp_json_encode($settings) . ";";

wp_add_inline_script('wpshopify-scripts', $this->stringify_settings($this->get_settings()), 'before');

The wp_add_inline_script function allows you to add arbitrary JavaScript before or after a registered script. So here, I’m adding a global variable called `wpshopify` which contains all of the plugin settings. Since this global is available before my main plugin JS script runs, the React settings app can easily use them.

Here’s an example of how I’m bootstrapping the initial settings state in React:

function SettingsInitialState(props) {
  const settingsModified = underscoreToCamel(wpshopify.settings.general)

  return {
    isLoadingPages: true,
    availablePages: false,
    isLoadingCollections: true,
    availableCollections: false,
    siteUrl: wpshopify.misc.siteUrl

export { SettingsInitialState }

Some of you may scoff at the use of a global variable and fair enough! However WordPress uses them and as long as you namespace them effectively I don’t necessarily seen an issue. Until WordPress implements something better I think this will work fine.

An Example: ShopWP 3.0

Below is a screenshot of how the upcoming ShopWP 3.0 admin settings page is looking so far.

The ShopWP settings screen

To decide how the overall layout would look, I took inspiration from two places: the new Site Health settings and the upcoming block directory designs.

Many people have not seen the block directory designs yet, but here are the current Figma design prototypes. I found this while listening to the recent Gutenberg Times podcast.

It doesn’t seem like there’s a true “standard” yet, but my own approach will be to mimic Core as much as possible. Whether or not the layout is centered or left justified is immaterial. What’s important is that we’re using the individual components.

Additional Resources

Without a doubt, the single best resource I’ve found that covers using these new React components is Zac Gordons JavaScript for WordPress. In particular, I received the most value from his Gutenberg Block Development and Advanced Gutenberg Development courses.

Hope this was helpful! Stay tuned for the next update.

See ya.

ShopWP 3.0 will require WordPress 5.0+

ShopWP Pro 3.0 Progress Update #1: Embracing the Future

On December 6th, 2018, WordPress 5.0 was released. It marked a turning point for the platform and represented a new vision for the most popular CMS in the world.

One year and over 22 core releases later, its adoption is starting to show. According to the official WordPress statistics, 68.6% of all WordPress sites are running at least version 5.0 or higher. While the number could be higher, I do think the tide is starting to shift.

Personally, I love the direction they’re taking the platform and I think it provides a unique opportunity for ShopWP to really shine.

For this reason, ShopWP 3.0 will require WordPress 5.0 or greater.

All previous versions of ShopWP will continue to work fine. So if you don’t want to upgrade, you won’t have to. However there will be massive performance benefits if you do.

At the moment, ShopWP loads many of the same assets that WordPress 5.0 includes out of the box, like React. It’s still a rough estimate but I’m currently noticing a 40%+ reduction in total assets that the plugin will have to load in 3.0. This is a huge deal! 🤯 This means faster loads times, which means more conversions for end-users of the plugin.

Additionally, there will be other “5.0 only” features besides a boost in speed. I will also be releasing custom Product blocks for ShopWP Pro users. I’ve been working on them recently and they’re amazing! I can’t believe we used shortcodes for so long. I’m really excited to show a preview in a future 3.0 progress update.

Overall, I couldn’t be more excited for the future of WordPress and as a plugin developer, I want to help manifest this vision. So join me and let’s embrace the future together! 🚀

ShopWP how to image zoom

How to series #1: Image Zoom

Product images in ShopWP have the option of showing a “zoom” feature that many of us have grown to expect from stores online. Before we get started, let’s walk through a few important things to know beforehand.

First, Image Zoom is only for product images and will not work for collections. It’s also a pro-only feature.

Second, Image Zoom will only work for the featured image of each product. For example, if you have five product images the four thumbnails that show at any given time will not have zoom applied. Only the active featured image.

Lastly, Image Zoom is turned off by default. Therefore, assuming you’re using ShopWP Pro the first thing you need to do is turn it on. You can do this from one of two places; either globally in the plugin settings or within each shortcode.

Let’s go through each one.

Enable Image Zoom Globally

If you want to turn on image zoom for all products, then you’ll need to enable it globally. You can do this from within the plugin settings.

First, open your WordPress dashboard and click the ShopWP sidebar menu link.

How to find the ShopWP settings navigation

From here, you’ll want to click on the “Settings” tab and then the “Products” sub-nav. You can then find the image zoom setting under the “Featured Images” heading.

An example of the ShopWP settings screen

Enable Image Zoom in Shortcodes

If you’d prefer to keep Image Zoom disabled globally, but enable it only for specific shortcodes, you can do so by using the show_zoom attribute. You’ll add this attribute to the [wps_products] shortcode like this:

[wps_products show_zoom="true"]

The show_zoom attribute only takes “true” or “false” as values. False is set by default which means Image Zoom is turned off.