< Blog

How to publish your own WordPress plugin

Review

Everybody, who is familiar with WordPress, uses plugins from its repository, it's a very simple and easy way to extend default capabilities. If you were developing or customizing a theme, how many times have you copied the same code from a previous website to a new one? How many times did you get an idea that your current feature would be helpful for others? If you've had similar thoughts then in this article we’ll show, with an example, that publishing your own plugin is not as complex as you may think. Those, who already have knowledge about publishing plugins, can use the article as a reminder for future publications, we’ll also share a couple of tricky things that you'll need to pay attention to.

Part A. Plugin creation

Note: If you already have experience with plugin creation then feel free to skip this section.

In this article we’ll use our plugin ACF Views (the simplest way to display ACF fields on front-end without coding). Down the line, don’t forget to replace this name with your own plugin name.

For those of you who are completely new at creating your own plugin here's a short overview:
WordPress plugins for your website is located in the /wp-content/plugins folder, and every plugin has its own folder. When creating a plugin you won't have as many steps as when you're creating a theme : you just need to create a new folder in the /wp-content/plugins directory and a single file inside (usually the file has the same name as the folder). In our example it’ll be /wp-content/plugins/acf-views/acf-views.php.

In the file, add the following 'header' comment. It’s necessary to include this in any plugin, as it lets WordPress know there's a plugin there.

<?php
/*
Plugin Name: ACF Views
Description: The simplest way to display values from custom post fields anywhere on your site using shortcodes.
Version: 1.0.0
Author: WPLake
*/

(Each line has a format : “Name: Value”, if you’re copied our header, simply change the values to yours). See all header requirements.

That’s it.
Your plugin has been created, you can visit your admin plugin page to see the new plugin in the list and you can also activate it. Obviously, the plugin does nothing yet, so after the header comment you should add your code (best regards, your captain), and all your features. The main plugin file can have (include/require) other files that should be placed in the same folder. More details about creating a plugin can be found here.

Part B. Preparing the plugin for publishing

At this stage the plugin which you would like to share with the world would already be created and tested by yourself.
Now let’s prepare the plugin for publishing:

1. Check plugin name

You have to choose a unique name that isn’t used by other plugins. To check if a name is available, copy https://wordpress.org/plugins/search/my-plugin/ (insert your plugin name instead of 'my-plugin') - if you see a page with search results (like with the my-plugin case) - it’s good news, the name is available. If you see plugin’s page, as in the case with ACF Views then it means the name is already in use and you have to choose another name.

2. Insert plugin file headers

Fill the main plugin file headers as complete as possible. Minimum required values are Plugin Name, Version, and Author. See the full list of header requirements.

<?php
/*
Plugin Name: ACF Views
Plugin URI: https://wplake.org/acf-views/
Description: The simplest way to display values from custom post fields anywhere on your site using shortcodes.
Version: 1.0.8
Author: WPLake
Author URI: https://wplake.org
*/

3. Create a readme.txt file

This file is your main opportunity to share information about your plugin with the world. This file will be parsed by WordPress, and it's this content that will be displayed exactly as is on your plugin page (the information is automatically parsed, you’ll have no admin panel on Wordpress.org to edit the content), see the ACF plugin page for another example.

Below is our readme.txt sample, required sections are : 
main (with your plugin name and data), description (about), and changelog (short data about your updates, at the beginning there'll only be one line)

=== ACF Views ===
Contributors: wplake
Tags: acf, display custom fields, acf views, shortcode, widget, custom fields in frontend, show acf fields, get field values, post, page, custom page, custom post
Requires at least: 5.5
Tested up to: 6.0
Requires PHP: 7.4
Stable tag: 1.0.8
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

The simplest way to display values from custom post fields anywhere on your site using shortcodes. Don't need to write PHP code to get field values.

== Description ==

ACF Views is the simplest way to display values from custom post fields anywhere on your site using shortcodes. This means you don't need to write PHP code to get field values, and you don't need to read documentation about field's return formats.

The views are reusable and shortcodes can be pasted ANYWHERE that supports shortcodes (e.g. Gutenberg shortcode block) with ANY THEME and ANY PAGE BUILDER.

**Important!** ACF Views plugin requires an active Advanced Custom Fields PRO plugin.

== Changelog ==

= 1.0.1 (2021-06-09): =
- Screenshots, plugin's version

Here's a full list of all available readme options.

Okay, we’ve managed to go through all the main steps, now let’s talk about the plugin’s code.

4. Check requirements for the plugin’s code

Here's the list of all requirements, the list has about twenty items but the most important is far less, these are as follows:

License

Your code must be available under GPLv2 or later (that means, you allow others to use and modify your code with the condition that they keep the original information about the author (You) and these rights (to use and modify for other people). In reality it means you shouldn’t use code parts with a closed license in your plugin. E.g. if you’ve written a feature on behalf of or as a request from a client, ask permission from them before using that code in the plugin.

Code Quality

Your code must be readable. Remember that your code will probably be read by other people (usually with the goal to understand how it works, or to clarify something or to extend it further). Don’t use pointless names of variables, classes and functions, like $asdre or function werlsdf(). Overall, be a good person coder and use the same code structure that you'd like to see in other plugins.

Safe Output (echo)

This is a very important point. WordPress requires ‘late’ data clearing from plugins.

What does it mean?
Let’s say you have $_GET variable - email, and you need to display it somewhere on a page. Most likely, you’ll do something like this :

$email = sanitize_text_field($_GET['email']?? '');
// ...
echo "<h3>Hi, {$email}</h3>";

And it’ll be a wrong. By WordPress rules for plugins (created to decrease the amount of vulnerable plugins, it's often for this reason that WordPress websites are hacked) regardless of the fact that you’ve already cleared a variable before or not, you MUST sanitize any variable in the output too. So use  esc_attr, esc_html functions, and in this case the output must be :

echo sprintf("<h3>Hi, %s</h3>",esc_html($email)) 

Don’t be lazy, search for ‘echo’ and check all your outputs, during the plugin review this step is often overlooked, and if you’ve skipped this step you’ll be notified about it and the review of your plugin will be paused until you’ve fixed it.

Composer Packages

Another rule, from us personally.

Unfortunately WordPress doesn’t provide a solution yet for common usage of composer dependencies between plugins, in this way a plugin can use one version of a dependency, and another plugin can use another version of the same dependency (believe us, it happens more often than you can imagine). In this case a user will experience a critical error and the website will be down. If you use composer dependencies in your plugin, make it non-conflict by using PHP-Scoper.
In short, it’s a tool that will add your namespace to all dependency files, and instead of ‘namespace Dependency\Folder;’ it will be ‘namespace YourNamespace\Dependency\Folder;’ In this way conflict is avoided, and the same dependency can be used by different plugins even with different versions. PHP-Scoper does it for you automatically, and the installation and setup is pretty easy and fast. Read more about using the PHP-Scoper tool for WordPress plugins.

Part C. Submitting your plugin

At last we’ve reached the most solemn and exciting moment. It’s time for assaulting the WP repository sending a request for placing your plugin on WordPress.org. It’s totally free and pretty easy.

First of all, you’ve to sign up on WordPress.org (if you haven't already), confirm your email and then visit the special request page.

Here you can upload your archive with the plugin (an ordinary archive, but includes a folder of your plugin, not only files without the plugin common folder), WordPress will do parsing of the archive and will display your plugin name that it will have in the WordPress repository (in our case it’s acf-views) and will display a notice, that the plugin name can NEVER be changed once approved. So please think twice, before pressing the submit button.

After submitting, the plugin will go through a manual review (usually within 1-5 working days) and you’ll be notified about approval/rejection of your request. In fact if your plugin isn’t malicious and your code quality is decent then you’ll never get rejected.

If the reviewers have noted some violation of rules (in our case it was about safe echo, we had cleared variables in the receiving time, not at the output time) then you’ll be notified about it with details, and requested to fix and submit an amended copy. If you followed all the points about plugin preparation from this article then reviewers should have no questions for you. Also, we would like to reassure you, because communication with WordPress reviewers is always an exciting experience (at least for us XD). We can honestly say, we've very rarely met such great support and if your plugin has some drawbacks then these will be noted in detail in the reviewers feedback, so you’ll immediately understand what you’ve done wrong. We’ve never had a case, where a plugin was not published or the reviewing was paused without any clearly defined reason, for which we want to say a big thank you to the WordPress community.

Part D. First commit

You sent a request, waited a few long working days (they'll probably feel very long for you) and at last you’ve received a letter, invitation to Hogwarts, a message that says your request is approved.

Congratulations, the plugin hosting request for ACF Views has been approved.

Within one (1) hour your account (X) will be granted commit access to your Subversion (SVN) repository.

* SVN URL: https://plugins.svn.wordpress.org/acf-views
* Public URL: https://wordpress.org/plugins/acf-views

Once your account access has been activated, you may upload your code using a SVN client of your choice. If you are new to SVN (or the Plugin Directory) make sure to review all the links in this email.

To answer some common questions:

* You must use SVN to upload your code -- we are unable to do that for you
* Your SVN username is X and your password is the same as you use to log in to WordPress.org
* Your username is case sensitive
* SVN will not accept your email address as a username
* Due to the size of the directory, it may take 72 hours before all search results are properly updated

To help you get started, here are some links:

Using Subversion with the WordPress Plugin Directory:
https://developer.wordpress.org/plugins/wordpress-org/how-to-use-subversion/

FAQ about the WordPress Plugin Directory:
https://developer.wordpress.org/plugins/wordpress-org/plugin-developer-faq/

WordPress Plugin Directory readme.txt standard:
https://wordpress.org/plugins/developers/#readme

A readme.txt validator:
https://wordpress.org/plugins/developers/readme-validator/

Plugin Assets (header images, etc):
https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/

WordPress Plugin Directory Guidelines:
https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/

Block Specific Plugin Guidelines:
https://developer.wordpress.org/plugins/wordpress-org/block-specific-plugin-guidelines/

If you have issues or questions, please reply to this email and let us know.

Enjoy!

--
The WordPress Plugin Directory Team
https://make.wordpress.org/plugins

In the letter the plugin SVN repository address will be declared (don’t worry about SVN, it’s similar to Git) along with a link to your plugin page on WordPress.org. You can save the letter (for history) but don’t worry about losing it, all links on WordPress.org are identical, so you only need to remember your plugin's name and you’ll always be able to find your links again.

Copy the links below, and replace 'PLUGIN-NAME' with your plugin name at the end:

https://plugins.svn.wordpress.org/PLUGIN-NAME 
https://wordpress.org/plugins/PLUGIN-NAME

We believe the name of your first love plugin won't easily be forgotten.

It’s time to release your plugin to the community

This part can only be done by you, not by the WordPress.org team, and it means your plugin will only be available after the first commit. 

Create a folder and clone the repository (svn should be installed on your machine):

svn co http://plugins.svn.wordpress.org/YOUR_PLUGIN_NAME_HERE

then

1. Copy files

Copy all your plugin files (without the common folder) to the trunk directory.

Create a folder with your version (likely 1.0.0) in the tags directory and also add your plugin files there.

2. Choose a banner and icon

It's time to think about a banner (this appears at the top of your plugin page on WordPress.org) and a plugin icon (that appears on WordPress search result page next to your plugin name). It can be any image you'd like (but no indecent pictures), you can add the banner in a couple of supported dimensions (772x250px width x height and 1544x500px) to the assets directory with the ‘banner’ label in the name.

It will therefore be banner-772x250.png and banner-1544x500.png (or jpg). The icon will be icon-128x128.png and icon-256x256.png (or jpg).

3. Add the files to SVN

Add the files to SVN with the commands:

svn add trunk/*
svn add tags/YOUR_VERSION_HERE
svn add assets/*

4. Commit

At last your first commit:

 svn ci -m "v 1.0.0"

(here the console will ask your WordPress.org account name and password, paste to authorize). Committing will take some time (svn isn’t as fast as git), so please wait some time until the command has finished.

Nice Job! Now you can visit your plugin page, it’s available for everyone, and you can install your plugin on any WordPress website directly via the admin panel (with Add new -> search).

Extra tip: Updating your plugin

After some time, you will (probably) want to add features/amend your plugin. For this goal you have to release a new version.

FYI:

An ordinary versioning is being used, and consists of 3 digits, like in npm or composer - Major.Minor.Patch. For example 1.0.0 - with small changes we increase only the third digit, 1.0.1, with adding new features or middle updates we change the second digit, 1.1.0, and with really big or ‘revolutionary’ changes we update the first digit, 2.0.0. In npm/composer it’s being used to manage your further updates, e.g. if you use ‘1.0.0’ version, by default you receive only Minor and Patch updates, but not Major, because it’s supposed that Major can contain changes without back compatibility. BUT WORDPRESS DOESN'T HAVE IT. It means you MUST provide back compatibility with previous versions. (For this goal there are special hooks that are called in the updating process, and can be used for DATABASE updates or other changes, to provide moving from the previous Major version to a new one, but you don’t need it at this moment).

It’s time to release a new version.

For this goal you'll need to:

1. Update plugin files

Update version in the main plugin file header (“Version: X”) to the new one (e.g. 1.0.2) and update “Stable tag: YOUR_VERSION_HERE” to the new one in the readme.txt file.

2. Update files in the SVN repository

Update the plugin files in the trunk folder and create a new folder with your new version number as a name in the tags folder, copy your plugin files to there too.

3. Commit

Let's let svn know about new files that were added and make a commit:

svn add trunk/*
svn add tags/{YOUR_VERSION_HERE}
svn ci -m "v YOUR_VERSION_HERE"

The description of the commit can be any, but we recommend that you use a version number as a description.

Summary:
You have to update the trunk directory (it always keeps the latest version) and add a new folder (with your new version as a name and with the plugin files inside) to the tags directory.

In case you just want to update the plugin information on the WordPress.org page, you can just update the readme.txt file in the trunk directory and commit in svn, without releasing a new version.

As you’ve noticed, the WordPress SVN repository is being used ONLY for releasing new versions (so it’s a release repository). It’s prohibited to commit every change to the repository like with git. Read more about using subversion. Otherwise your repository will become very slow, and will use a lot of space on the WordPress.org side. For plugin developing create your own git repository and commit as often as you want, using the svn repository only for releasing new versions. 

We hope this article was helpful to you, and destroyed the myth that publishing your own WordPress plugin is difficult and takes a lot of time. Time to make this world better and publish your own plugin!

Instead of P.S.

In this article as an example we've used our ACF Views plugin. If anybody is interested to know more then keep reading. It’s a plugin-extension to Advanced Custom Fields plugin (PRO version of ACF is necessary to use ACF Views).

What problem does it solve?

The ACF plugin is very useful and intuitive, and in fact became a plugin that's included by default at the start of a developing package of any website, but anytime you’re creating a new group and assigning it to a page or Custom Post Type (CPT) then a question, a task appears - to display these fields on the website frontend.

Usually it's done manually (for example in a theme) - it creates a shortcode that inserts fields into some markup and displays it, then this shortcode is pasted on a page/CPT template and provides styled output.

But there are a few of these moments, like:

  • Editing a theme manually every time (usually a child theme)
  • ACF has a lot of field types, and each has its own return-format (that accept the field type) dependent also on the specific field settings, e.g. an image field will return an image ID or an array with image data, during markup creation you’ve to take care of it, and every time check official documentation to clarify return format of a specific field.
  • For styling usually global styles are being used, right in style.css of a theme (or in theme settings if the theme supports it). As a result, the amount of such code increases and it has a negative impact on site speed, not to mention the amount of conflicts with elements on different pages.

ACF Views makes life easier and displays Advanced Custom Fields (ACF) on a website front-end by itself. After creating a field group, you create a View, choose which fields you want to display, save/update and get a shortcode. Copy and paste the shortcode on a target page/CPT and voila, the output is ready.

The Plugin automatically generates HTML markup depending on the field types and its settings (supports many types and all return formats). To style output you can add styles right in the View (there is a special field), these styles will be printed only on pages where this View is (not globally), and markup has classes by default (in BEM style), so you can use them without setting up your own. Download the latest version of ACF Views. There is an ACF Views PRO version that allows you to edit HTML markup (still without worrying about types and return formats), make use of repeater fields and easily switch on Gutenberg blocks without any coding. (Here's is a special promo code for blog readers - wplakeblog9, you’ll get 20% off at checkout).

Got it