Categories
Posts

Launching WPJobManager.com

I’m happy to announce I’ve finally flipped the switch on WPJobManager.com, a site which I’ve been working on for a few months now in my spare time. I felt it was about time that I had a better sales platform and a dedicated place for the plugin which has been steadily growing in popularity during the past year.

WP Job Manager download stats growth
WP Job Manager download stats growth

Up until now I’ve been selling add-ons via Gumroad. It’s a fun service, and it’s easy to use, but it lacks the flexibility I need. In particular I’m talking about licences. Without some kind of licencing system I have no way to verify a customer when it comes to updates and support, the sale is one off (something that’s not sustainable with this type of product), and I have no way to limit distribution of my plugins.

Its alive Therefore, I made the decision to switch over to WooCommerce (what else?) and have a proper marketplace for the plugin. Hosted on DigitalOcean and powered by WordPress and WooCommerce, WPJobManager.com is now live.

Continue reading “Launching WPJobManager.com”

Categories
Posts

6 ways to polish a plugin before release

Before you release your plugin on WordPress.org it’s always good to spend a little time polishing the final product; not only does this make your job easier in the long run (so you don’t have to fix it later), it gives a better first impression to new users.

Continue reading “6 ways to polish a plugin before release”

Categories
Posts

Plugin development and the fear of change

2255781557_d7148597a7_z

Yesterday I was taken off guard with a comment/concern from an anonymous WooCommerce developer named “Jonathan”. Jonathan was annoyed at upcoming changes in the core WC plugin:

Mike, one thing that strikes me about WC as compared to WP is stability of maintstay features and code structures. Notice that WP rarely breaks a site.

He went on to compare WordPress to WooCommerce:

This is something all the devs of WC should take careful note of. As a glaring example, WC 2.1 will break a lot of plugins. I know this to be fact our company has developed dozens upon dozens of custom plugins for WC for our customers.

Jonathan’s personal feeling was that plugins should avoid change. His main gripe was our ‘restructuring’ of core classes.

But it’s simply an ideological / philosophical tree structure decision that makes no difference in the overall operation of the software

Yes, we could have left them as they were and not much would change operationally. But the old structure was a mess and inflexible.

To explain a little, we had a classes folder, function files willy nilly, a separate admin folder with more classes inside etc. Anyone coming into WC development would see this and think “WTF are these jokers doing?”.

So yes, whilst we could have left them alone, we changed them – this will improve the plugin structure long-term, even if that means breaking some things short-term (note however: we didn’t envision this particular change could break anything).

I put the question to twitter:

There were some interesting replies, and the decision was unanimous from both plugin developers like Pippin, and freelancers like Sean; Improve and Change > Supporting legacy.

You can view the full conversation here if you wish: https://twitter.com/mikejolley/status/414837248572796928

WordPress isn’t perfect

Jonathan’s argument stemmed from the fact WordPress doesn’t break things often. But remember it still does.

Take MP6 for example; 3.8 changed the look and feel of WordPress admin, as a result styling in many plugins has been “broken”, including menu icons. Now, albeit not a site-breaking change, it means all < 3.8 plugins will need to make some visual alterations.

And what about the major updates 1.0 -> 2.0, 2.0 -> 3.0 – I’m certain plugins built for 2.0 would fail for 3.0, so why would WooCommerce 1.0 to 2.0 be any different? You shouldn’t expect your code to work forever.

Why changes are important

Whether they be features, refactors, or file structure changes, changes are important. Without making these decisions your plugin cannot evolve – you don’t want to be stuck with a v1.0 forever. It’s natural for things to crop up after the first release and after some real-world usage. Users will find bugs, oversights, or simply won’t be able to work with the plugin as they want to. Thats why you need to make the hard decisions for the greater good.

I can give you an example of a plugin-breaking change in WooCommerce. The order system in WooCommerce 1.0.x used post meta to store line items. This worked perfectly fine but with real-world usage it meant:

  • queries of line items were extremely heavy
  • serialisation of data was slow
  • the system was inflexible
  • a slight error in line item data would break all lines

So we created a custom table in 2.0 to store line items and the system is now way more stable. This change would have broken any plugin using those old meta fields directly, but it was necessary.

If you don’t improve, someone else will

You need to keep up to date with new features and enhancements. If you don’t someone else will, either with a fork or with a new competing plugin. Let us take an eCommmerce plugin example.

WordPress 3.0 “Thelonious Monk”, was released June 17, 2010 with the revolutionary new ‘custom post types’ feature.

Shopp, one of the biggest eCommerce plugins at the time, up to then was using its own custom tables and UI for products simply because no other core alternative was available.

It took 2 years for Shopp to support custom post types (Feb, 2012) and in that time countless new eCommerce plugins were released; WooCommerce, Jigoshop, eShop, Marketpress to name a few. Shopp had to lose many users over this, an example in their comments:

Too late for me. I wish you guys all the luck as you were there when I needed you years ago, but I’ve been seeing other shopping carts and they are getting all the future love.

See my point? I’m sure a large factor in this delay was the fear of change and backwards compatibility, but sometimes you’ve just got to say “screw it” and get the ball rolling before its too late.

What plugin developers should do

Keep backwards compatibility if possible

If its possible to keep backwards compatibility, even for a few releases, you should. Use deprecated functions, fallbacks, and output warnings. Production sites shouldn’t break and shouldn’t show these, but development sites will and developers will be able to get their customisations updated before the site falls over.

Only make major changes in major releases

Don’t make site-breaking changes in minor releases – that would would be irresponsible. If you have to change a fundamental part of your plugin, ensure its a major release with an obvious major version update.

Announce it

It’s no good changing something un-announced and watching the havoc unfold; notify your users.

Blog posts, dedicated development blogs, in-plugin warnings and notifications, an ‘upgrade notice’ in your readme – all good ways of notifying your users. As long as developers utilising your plugin are listening, they’ll be able to act accordingly.

What client developers should do

If you’ve built something for a client, or a product on top of a plugin, you are ultimately responsible for its functionality.

Listen

Stay up to date with plugin developments, listen to announcements and ensure major updates don’t crop up without you knowing first.

Plan for maintenance

Understand it won’t be a build once, ignore forever chunk of code. You will need to plan updates and maintenance into your proposal, otherwise your clients will be stuck with old versions. Charge more, as Brian so bluntly puts it:

You wouldn’t sell a car and then fix it for free for life, so when you sell a plugin don’t do the same. Create a plan to deal with updates and do them as required.

Test

Test your code with major updates before running them. If you need to do this on behalf of your client, ensure they are aware of these costs up front.

Follow best practice

If developers tell you how you should be doing something, follow their guidance. In Jonathan’s case he has been including core classes:

We probably have to modify about 40 of them, simply because you guys decide to move files around in the core tree and no other reason. This is seriously bad practice and really ought to stop now.

We’ve never recommended this practice, nor provided any code, snippet or plugin which does this and whilst I cannot comment on whether or not he was right to do what he did, but it doesn’t feel right. We always recommend using the many filters provided, but if they weren’t suitable this leads me to my next point.

If something is wrong, make your case before it is too late

If you spot a problem in the plugin you are developing for, perhaps one you cannot work around, let the developer know. Otherwise, how can they help you?

In the case of WooCommerce we have both a development blog and github issues setup – tell us, suggest an alternative, get involved. If you do nothing you only have yourself to blame.

Sorry Jonathan

I know updates can be frustrating and appreciate your situation, but we’re working towards building a better solution overall. If that means breaking some custom code along the way, I honestly believe it’s well worth it in the end.

Please don’t give up, and by all means get involved – thats the beauty of open source, anyone can contribute their ideas, code and guidance.

Thanks for reading.

Photo by stuant63, CC-BY-2.0

Categories
Posts

Tweaking the donation monitization model

Most developers agree the donation model isn’t great (giving the plugin away for free and requesting, not requiring, a small donation as a sign of support).

Arguably the best alternative is freemium model (where you have a free plugin and build premium functionality plugins around it) which is growing in popularity and is used by plugins such as WooCommerce and EDD.

Freemium may not be suitable for all plugins however, as some may not have many features which you can make premium, or you may just want to avoid the burden of supporting users who’ve purchased a premium product (who’s expectations for support may be far greater).

One of my plugins, Download Monitor, has always been donation based and free on WordPress.org. Although there is space for a few premium extensions, I’ve not had the capacity nor will to build them yet. When I rewrote the core plugin however, I did take out a feature I deemed to be bloat and made it separate – but not premium, as I thought users would react badly to a previously core feature being made paid-for after an update. Instead I made it “pay what you want”.

Continue reading “Tweaking the donation monitization model”

Categories
Posts

Plugin installation techniques; activation, deactivation and uninstall

If you are building a complex plugin, or one which needs it’s own database tables, you’ll likely be installing all kinds of things during activation or first run. Uninstalling your data however may be an after thought.

In this post I’ll explain techniques you can use to install and remove your data to keep things tidy, should the user decide they no longer want your plugin.

Continue reading “Plugin installation techniques; activation, deactivation and uninstall”

Categories
Posts

Eight ways to contribute to a WP plugin (and why you should)

Contributing to a plugin you use (or use for client sites) can not only benefit the developer of the plugin, but can also benefit you (and other users) too. There are many ways to contribute to a plugin, not just in terms of development as well; anyone can get involved.

Continue reading “Eight ways to contribute to a WP plugin (and why you should)”

Categories
Posts

The importance of stating the obvious

Writing documentation and other supporting content can be hard, especially for plugins. Why? There are many levels of user; developers, web ‘assemblers‘ and DIY-ers, all of whom will need to understand your content. You may think you’ve covered everything, but things that are obvious to you may be well beyond what some users can grasp.

Take one of my plugins as an example, a WP Job manager addon called WooCommerce Paid listings:

Add paid listing to WP Job Manager functionality powered by WooCommerce

To me it’s pretty obvious that this plugin integrates Job Manager with WooCommmerce, but to date I’ve had at least 10 users boggled by the fact you need to install WooCommerce first to use it. That’s insane given the name of the plugin, and the descriptions I provide.

Continue reading “The importance of stating the obvious”

Categories
Posts

Use WordPress’ URL manipulation functions

WordPress comes with many useful functions developers can make use of in their plugins. Today we’ll look at the URL manipulation functions – add_query_arg and remove_query_arg, both part of WordPress core.

add_query_arg

Incredibly useful in plugin development, add_query_arg lets you reliably modify an existing URL by adding or changing it’s query arguments. So for example, if you want to append a query var named ‘page’ set to ‘2’ to the current URL, you could use:

add_query_arg( 'page', 2 );

It’s that easy – you don’t need to worry about the existing query string, or ‘?‘ And ‘&‘ characters as it’s all handled for you.

The function can be used in two ways:

For adding a single argument

In its simplest form, add_query_arg will let you pass a name, value, and optionally an $old_query_or_uri you wish to append the arguments to.

add_query_arg( $key, $value, $old_query_or_uri );

For adding multiple arguments

To add multiple arguments at once you only need add an array, and again optionally the $old_query_or_uri.

add_query_arg( array( $key1 => $value, $key2 => $value ), $old_query_or_uri );

In practice, let’s say we want to add some ordering arguments to a page in admin. We could use this:

add_query_arg( array( 'order' => 'asc', 'orderby' => 'title' ), admin_url( 'admin.php?page=myplugin' ) );

This would give us:

http://yoursite.com/wp-admin/admin.php?page=myplugin&order=asc&orderby=title

remove_query_arg

This function will remove single or multiple query arguments from a URL you define, or the current URL. To remove a single argument, pass a string:

// current url: http://yoursite.com/?order=asc&orderby=title
echo remove_query_arg( 'order' );
// echos: http://yoursite.com/?orderby=title

To remove multiple arguments, pass an array of string:

// current url: http://yoursite.com/?order=asc&orderby=title
echo remove_query_arg( array( 'order', 'orderby' ) );
// echos: http://yoursite.com/

Important: Don’t forget to escape!

This caught me out a few weeks ago when I found out (the hard way) that WordPress doesn’t automatically sanitize the current URL if you don’t pass in your own. You need to use esc_url during output:

echo esc_url( add_query_arg( $key, $value ) );

If you forget to do this, a malicious URL, for example one containing some JavaScript, could potentially be output and executed on your page. Escape all the things to be safe!

Categories
Posts

Avoiding feature bloat in plugins

As a plugin developer, if you release a product (no matter how popular), its a given that over time you’ll receive an influx of feature requests; some user somewhere thinks your plugin should do X to better suit their own personal needs.

Feature requests shouldn’t be dismissed as they can give valuable insight into your user base’s needs and some requests could be perfectly valid oversights on your part. But before coding, consider the impact of adding the feature, work out if it’s actually relevant, and ensure its not just bloat.

food
nom nom nom bloated

Feature bloat is defined as being defined as:

the tendency of a vendor continually to add unnecessary features to a product that are not of any value to most users, use more system resources than necessary, and often unnecessarily add to the cost of the product

Obviously you don’t want to add something for a single user that’s decremental to the majority, so think it through carefully. Striking the right balance is the key to success.

Continue reading “Avoiding feature bloat in plugins”

Categories
Posts

Sensible script enqueuing for shortcodes

If you are making a WordPress plugin which uses a shortcode, and said shortcode needs some Javascript enqueued in order to function, it may be tempting to just whack the script in the wp_enqueue_scripts hook and be done with it.

add_action( 'wp_enqueue_scripts', 'enqueue_my_script' );

function enqueue_my_script() {
wp_enqueue_script( 'script-name', plugins_url( '/js/script.js' , __FILE__ ), array(), '1.0.0', false );
}

Yes this works fine, and is perfectly fine during development, but as the script gets loaded site wide this can be terribly inefficient if the script is specific to your plugin.

To improve matters, you can employ some conditional tags to control where your script gets loaded. For example:

add_action( 'wp_enqueue_scripts', 'enqueue_my_script' );

function enqueue_my_script() {
if ( is_archive() || is_single() ) {
wp_enqueue_script( 'script-name', plugins_url( '/js/script.js' , __FILE__ ), array(), '1.0.0', false );
}
}

The above code would enqueue on single posts and within post archives.

For a shortcode however, this can be tricky; you know the shortcode can only be used within posts and pages, but a) thats pretty much site wide anyway and b) you don’t know if the shortcode is being used on the page you are enqueuing the script.

One way you can further optimise your enqueue would be to check the content of a post and see if it contains your code – but again, the drawback is that will most likely only work in certain situations, for example if your shortcode is intended to be used when viewing single posts only.

The sensible method

Forget conditional tags. Forget enqueuing site wide. Instead the solution is quite simple…

First, register your script early, don’t enqueue it.

add_action( 'wp_enqueue_scripts', 'register_my_script' );

function register_my_script() {
wp_register_script( 'script-name', plugins_url( '/js/script.js' , __FILE__ ), array(), '1.0.0', true );
}

At this point, WordPress is aware your script exists, but it won’t be loaded onto pages. Notice the ‘true’ in your wp_register_script call – this is important and tells WP that you want the script to be loaded in the footer of your page.

Next, and this is the best part, you can enqueue on demand. Now in your plugin where you render your shortcode simply add:

wp_enqueue_script( 'script-name' );

This will enqueue your previously registered script ready for output in the footer of the page.

Now you have a lazy-loaded script, and no need for fancy conditional rules – much better.