Develop and publish a plugin to the WordPress store

Have you ever wanted to publish your own plugin to the official WordPress plugin store? The process of developing your own WordPress plugin can be cumbersome and exhausting, as some things are proprietary to WordPress and need to be done in specific ways, but don't worry, I'm here to help 😄

Develop and publish a plugin to the WordPress store

Have you ever wanted to publish your own plugin to the official WordPress plugin store? The process of developing your own WordPress plugin can be cumbersome and exhausting, as some things are proprietary to WordPress and need to be done in specific ways, but don't worry, I'm here to help 😄

I recently had the pleasure of developing and publishing a WordPress-Plugin for our innovative, ai-driven image cropping software Croppy. You can check it out here: WordPress-Plugin-Store: Croppy

Things to consider, even before starting

Some things should be considered very carefully, before writing a single line of code. Otherwise, you might end up failing the review process of WordPress and need to adapt your code. (it happened to me, so learn from my mistakes)

  1. Your code must define a GPL-compatible License
    1. how you do that? Well I will explain that later on in the blog but just think about which license you would like to use
  2. Every piece of code you write in functions, classes etc. must be generic and with a custom slug in front of it
    1. this is due to the fact that WordPress hosts millions of plugins and there is the chance that someone has the same method as you, if there would be no slug, you would overwrite his method or vice versa
  3. All data, that your plugin uses must be sanitized, escaped and validated before being used
    1. WordPress offers a variety of sanitation methods, you must use them, details can be found later on
  4. No Iframe, no creation of users, no saving of files directly into the Plugin directory
    1. generally not allowed

Those were among the things that broke my neck when submitting the plugin for the first time. To be honest: If I had read the documentation thoroughly beforehand, it would have been easier :)

a racing car, that just startet the race

Ready, set, go!

As you have now considered the most important things and thought about what your plugin should and should not do, it is time to start our development process.

The first steps when developing

Create a directory for your plugin. The name you choose will be the plugin-slug, so be careful and choose one that you can use later on in the store as well.

When you have your directory, create a LICENSE.txt in it and copy the content of your preferred GPL-compatible license in it.

Then create a PHP file, that serves as entry point for your plugin. Your directory structure should now look like that:

a directory structure
You must change the slug to your desired name

Now open your PHP file and start is with

<?php
/**
 * Plugin Name: Blog Plugin
 * Plugin URI: https://XXXX.com
 * Description: Perfect description of the blog plugin.
 * Version: 1.0.0
 * Author: Kilian
 * Author URI: https://seadev-studios.com
 * Text Domain: blog-plugin
 * Domain Path: /languages
 * Requires at least: 6.4
 * Requires PHP: 7.0
 * Tested up to: 6.5
 * License: GPLv2 or later
 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
**/
  • The plugin name is self-explanatory.
  • The Plugin URI is the website of your plugin (if existent)
  • the text domain is the domain of your plugin, it should always match your plugin slug.
  • The domain path is the path where WordPress can find your translations for your strings (if you do not translate, just delete this line)
  • The requirements are basically the versions of WordPress and PHP that your plugin needs
  • the tested up to states up to which version your plugin has been tested.
  • Then specify your license again, and you are set.

The README

The README is basically the description, that is being rendered into the plugin store when you click onto a plugin. It is important to note that this will be one of the first things a potential user sees, so try to be as specific as possible when choosing what to write here.

It is written in Markdown. So you can make headers, lists, etc. Important to note is, that it must consist of four sections:

  1. Title of your plugin (yet again)
=== Blog Plugin ===
Contributors: kilian
Tags: blog, development
Stable tag: 1.0.0
Requires at least: 6.0
Requires PHP: 7.0
Tested up to: 6.6
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html

The best WordPress plugin to exist.
  1. Description
== Description ==
# Description of the Blog plugin.
...
...
  1. Installation
== Installation ==

General Information  on what is needed to run your plugin (external accounts for example)
  1. FAQ
== Frequently Asked Questions ==

= Question 1 =

Answer 1

= Question 2 =

Answer 2

Great job. That's it. Per definition, you have your own WordPress plugin. It doesn't do anything yet other than look good in the store ;), but we can change that.

a programmer that is focused on his work
Let's start coding.

The Coding

I will not tell you what to program and how. I will just tell you some things to consider and some things to do so that it works properly.

The first lines of code should be:

// Exit if accessed directly
if (!defined('ABSPATH')) {
    exit;
}

This ensures that your plugin file cannot be accessed via the browser.

Create a PHP function now, that initializes a menu item so that your plugin is accessible via the menu:

// Add menu item to left sidebar
function blog_plugin_add_menu_item() {
    // Add menu page with icon
    add_menu_page(
        'Blog Plugin',              // Page title
        'Blog Plugin',              // Menu title
        'manage_options',      // Capability required to access the page
        'blog_plugin',     // Menu slug
        'blog_plugin_page',// Callback function to render the page
        'dashicons-format-image',
        10                      // Position in the menu
    );
}

Notice the consistent usage of the plugin slug 😃

And the function to render the page is defined right away:

function blog_plugin_page() {
    ?>
        <div>
            <h1>
                Some HTML Content to render!
            </h1>
        </div>
    <?php
}

You can return any HTML you like and style the page as you wish. This is the component of your plugin that will be seen and interacted with by the user directly. So style it to be appealing.

And to trigger the creation of the menu item, add the following code somewhere into the PHP file.

add_action('admin_menu', 'blog_plugin_add_menu_item');

This tells WordPress to render your menu item as soon as the admin menu action is triggered.

That's basically it. I will now tell you a few things you can use if you would like to, but the general blog is now finished!

Good to know

Some things are good to know but not mandatory to use, under this category falls everything that I will explain now:

Add CSS and JQuery Code to your plugin

First things first, add the following code snippet:

add_action('admin_enqueue_scripts', 'blog_plugin_custom_scripts');

Then create the correlating function:

function blog_plugin_custom_scripts() {
    wp_enqueue_style('blog-plugin-custom-style', plugins_url('css/styling.css', _FILE__), array(), '1.0.0');
    wp_enqueue_script('blog-plugin-custom-script', plugins_url('js/script.js', __FILE__), array('jquery'), '1.0.0');
}

Of course, you would need to create both the style.css and the script.js file in the corresponding directory within your plugin directory.

Sanitize Input, Escape Input, Validate Input

WordPress offers some cool methods to do those things completely automated.

  • esc_html_e()
    • displays translated text and escapes it for safe use in HTML output
  • sanitize_text_field()
    • sanitizes user input from a text field on your plugin page
  • wp_unslash()
    • removes slashes from a string (recursively)

Whenever your application deals with dynamic user data, remember to sanitize, escape and validate this data before doing anything with it.

Translating your Strings

Translating your plugin provides you with certainty, that no auto-translation misinterprets your plugin and that all users around the world see the correct translations.

The .po Files

Those files are used to define all the messages and translations that you have.

The structure is as easy as could be:

msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: de_AT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "Logout"
msgstr "Ausloggen"

Define your message IDs and your message strings. Before all the strings, change the language tag to your actual language. The rest should be good to go.

Then save the file with the following name:

blog-plugin-de_DE.po

The locale and the slug of course change, but the syntax is important. Also, the locale must match the language tag within the .po file.

The .mo Files

Are actually binary representation of your .po files and are the translated, interpretable version of your translations so that WordPress can use them.

Creating the .mo Files is easy:

msgcat yourFile.po | msgfmt -o generatedFile.mo -

That's it.

Usage of the translation in the plugin code

Important is, that the text-domain matches your plugin slug (in my case blog-plugin) and that the .mo files have the name blog-plugin-LOCALE.mo so that WordPress can find them.

Now you can just translate any string with:

esc_html_e('Logout', 'blog-plugin');

Finished.

interconnected world, driven by technology

Publishing your form

Go to this page here and submit the submission form: https://wordpress.org/plugins/add/

They will test and review your plugin code thoroughly, but if you stuck to this blog, that will be no problem.
As soon as the review process is done, you can upload the plugin code to SVN. These steps are already well documented.

If you have got any questions about any step that I have explained on how to publish a WordPress plugin, do not hesitate to leave a comment!

Thank you for reading and I wish you all the best.