Is it time to say goodbye to your WordPress website?

Maybe it’s time for a fresh start, or perhaps you want to distance yourself from the kind of content you used to create—whatever your reasons, you probably won’t want your abandoned website hanging around on the Internet forever.

In this article, I’ll show you how to permanently delete your WordPress website, regardless of whether you created your site via or And, if you got carried away and created multiple websites, then I’ll also be showing you how to delete all of these sites simultaneously, by cancelling your WordPress account. vs. What’s the Difference?

The process for deleting your website will differ depending on whether it’s a or a site, so let’s start by clarifying the differences between the two:

  •, sometimes referred to as self-hosted WordPress, is where you download the free WordPress software and install it on your own server. With a website, you’re solely responsible for hosting and maintenance. 
  • takes care of the hosting for you. Rather than downloading and installing the WordPress software, simply head over to, click Get started, complete a few forms, and will create your website for you.  

The Internet Is Forever

In this article, I’ll show you how to delete your website, so it no longer appears at its URL or appears in Google search results. However, if your website has been archived by third parties then there’s a chance your content will still be accessible via these third-party services. 

Deleting your website will make it less accessible, but there’s no guarantee that a determined third party won’t be able to recover some or all of your deleted content. 

How Do I Close My Account?

Are you performing some admin and want to delete all the accounts that you no longer use? Or perhaps you want to delete your existing WordPress account, so you can re-register and start again from scratch? 

When you close your account, WordPress will also delete all the websites associated with that account. If you got carried away and created multiple different websites, then cancelling your account may be easier than deleting each website individually.  

To close your account:

  • Log in to your account, if you haven’t already.
  • Head over to the Account Settings screen.
  • Scroll to the bottom of the screen and select Close your account permanently.
Cancel your WordPress account by navigating to Account Settings and selecting Close your account permanently
  • Review the list of content you’re about to delete, and if you’re happy to proceed then click Close account.
Review the items that will be deleted and if youre happy to proceed click Close account

WordPress will now delete your username, all the sites you own, and all of your content. 

Deleting a Blog From the Dashboard

If you created your website via, then you can delete it directly from the WordPress Dashboard. Note that when you delete your website, you’ll also lose access to your site’s URL unless you purchased the domain. 

To delete your site, first log in to your WordPress account, if you haven’t already.

In the left-hand menu, select Manage > Settings. Now scroll to the very bottom of the screen and select Delete your site permanently.

At this point, you’ll have the option to export all of your posts, pages, and settings as a ZIP file. If you ever change your mind and want to reinstate your website, then you can upload this ZIP file to a new WordPress site and recover your content. This step is optional, but it’s also a one-time offer: if you don’t export now, then your content will be lost forever. If you do want to hang on to a copy of your content, then click Export all. Once the export is complete, click Back to resume deleting your website.

Review all the information about the content you’re about to delete, and if you’re happy to proceed, then click Delete site. When prompted, enter your website’s full URL for a final confirmation. 

This is it! If you’re still determined to permanently remove your website from the World Wide Web, then click the Delete this site button and your WordPress website will be gone forever.  

How to Delete Your Self-Hosted Website With cPanel

If you used cPanel to set up your self-hosted WordPress website, then you can also use cPanel to delete it:  

  • Log in to your cPanel Dashboard.
  • Select the Hosting tab. 
  • Find the website that you want to delete and click its accompanying Switch button.
  • On the subsequent screen, select WordPress
  • Select Uninstall. After a few moments, you should see the following message: Software has been uninstalled.

Your WordPress website has now been deleted.

Delete Your Self-Hosted WordPress Website Manually 

If you installed the WordPress software on your server manually, then you’ll also need to remove it manually. This process can vary depending on whether you have FTP or SFTP access, or you access your web server via a web-based file manager:

1. I have FTP or SFTP Access

If you have FTP or SFTP access, then you can delete your WordPress website using an FTP client:

  • Log in to your FTP server. 
  • Locate your WordPress directory, and either Control-click or right-click it, depending on whether you’re running Windows or macOS. 
  • When prompted, select Delete.

2. I Use a Web-Based File Manager

If you have access to a web-based file manager, then:

  • Log in to your web hosting dashboard.
  • Open your file manager application.
  • Navigate to the WordPress directory that you want to delete, and hit the Delete button. 

Delete Your Website’s Database Using MySQL

After deleting your WordPress website, you may also want to delete your website’s MySQL database. You can remove this database using the following MySQL command: 

$ mysql -h HOST -u USERNAME -p PASSWORD -D wordpress
$ DROP wordpress

Note that you’ll need to replace wordpress with the name of your WordPress database, which is located in your wp-config.php file. The process for locating this database will vary depending upon your hosting provider—for example, if you were using cPanel, then you would typically use the file manager to browse to your WordPress directory, which contains the wp-config.php file.

Delete Your Database Using cPanel

If you’re a cPanel user, then:

  • Log in to your cPanel Dashboard.
  • Scroll to the Databases section, and select MySQL Databases.
  • Select the MySQL database that you want to delete.
  • Find the Delete Database link, and give it a click. 
  • Read the onscreen warning, and if you’re happy to proceed, then click Delete Database.

cPanel will now delete your website’s database. 


In this quick tip, I showed you how to permanently delete your or website, and how to optionally delete your site’s MySQL database. 

Are you deleting an outdated WordPress website with the intention of starting again from scratch? If you’re creating a brand new WordPress website, then be sure to check out some of our other WordPress tutorials, as they contain all the information you need to create a modern, professional, and engaging WordPress website. 

The Best WordPress Plugins on CodeCanyon

Explore thousands of the best WordPress plugins ever created on CodeCanyon. With a low-cost one time payment, you can purchase these high-quality WordPress plugins and improve your website experience for you and your visitors. 

Here are a few of the best-selling and up-and-coming WordPress plugins available on ThemeForest for 2020.


When you build a WordPress website, you open yourself up to an entire world of possibilities. That is both a good and bad thing.

The built-in conveniences and ability to extend functionality with just a few clicks make site owners feel at ease. The bright side is that this allows us to do more with a shoestring budget than we may have thought possible. But it can also lull us into a false sense of security.

The result is that we may be putting our websites at risk without fully realizing it. WordPress, after all, is not a set-it-and-forget-it CMS. On the contrary, it requires us to develop good practices and constant vigilance.

Here are five bad habits that, while innocent in intent, can bring unwanted drama to your WordPress install. We’ll cover both what can go wrong and provide simple solutions that will help you avoid future problems.

Leaving Unused Plugins Installed

It’s a pretty common practice. We search through the WordPress Plugin Repository and find something of interest. We install it and plan on seeing what it can do. However, maybe it isn’t a great fit, or maybe we never test it at all. Still, it sits there.

Keeping unused plugins around can be costly. From a security perspective, it can be dangerous. A vulnerable piece of code could very well lead to malware being installed on your server. This could, in turn, do untold amounts of damage to your site.

The unfortunate truth is that not all plugins are well-written or maintained. Some are even abandoned by their authors. If you happen to be the unlucky person who still has one of these plugins installed, you are a target.

Beyond that, the more plugins you have installed, the harder it is to troubleshoot any errors that arise. Clutter only serves to complicate the process.

The Solution

It’s okay to install plugins and test them out (preferably on a staging site). But make a habit of removing unwanted plugins – even those that aren’t currently active on your website. Routinely browse through your WordPress back end to check for items you don’t need.

Vehicles in a junk plugin and make sure your install is up-to-date. It won’t stop every potential attack, but it can thwart the basic stuff.

A cat sleeping next to a computer.themes available. But there are times when commercial software just makes more sense. It might be a better fit for your needs or offer more powerful functionality. Plus, commercial-grade support is always welcome when it comes to mission-critical tools.

However, these items take often take a sustained financial commitment, as one-time purchases are becoming rare. Much of the commercially-available plugins and themes for WordPress tend to require yearly license renewals.

This recurring cost helps the developer provide support, add new features and fix bugs. It means that the software will continue to be actively developed, which benefits everybody.

Yet, I am still amazed at how often I see websites using software with long-expired licenses. This can be both a security and functionality nightmare. Eventually, something is going to either become vulnerable or break altogether as new versions of WordPress are released.

The Solution

Do some research before you buy a plugin or theme. Determine what the future costs will be and if they are manageable. Just as importantly, inform your clients about these licenses! Quite often, a license will expire simply because a client doesn’t know about it.

Man looking through his wallet.SEO – there are so many options for each. Collect enough of these plugins and eventually, a few are going to patrol the same territory.

The Solution

When possible, choose a definitive path for the functionality you need in any particular category. Either find a plugin that does just about everything you want, or piece together a few niche items.

This is where a plugin with its own ecosystem, such as WooCommerce, makes life easier. Through its many extensions, you can add just the capabilities you really need – thus avoiding overlap.

A pile of clocks.backup plugin. There are also a number of third-party services such as ManageWP, InfiniteWP or even Jetpack that offer similar functionality.

Whichever you choose, be sure to keep a copy of your site somewhere other than your web host. That could be a cloud storage service or even your local machine. That way, you’ll always have access – just in case.

Broken hard drive.maintenance, you can often avoid the most serious kinds of problems.

Not sure you’re up to the challenge? Start off with something simple, like setting a weekly reminder to update your installation. From there, set a monthly reminder that urges you to take inventory of plugins and security.

Follow that plan and, pretty soon, your website will be in tip-top shape.


About The Author

Leonardo Losoviz is a freelance developer and writer, with an ongoing quest to integrate innovative paradigms (Serverless PHP, server-side components, GraphQL) …
More about

Making our code CMS-agnostic, as much as possible, enables us to easily port our application to another CMS if the need arises. In this article we will learn how to abstract a WordPress application, making its code readily available for other frameworks or CMSs.

In the first part of this series, we learned the key concepts to build an application that is as CMS-agnostic as possible. In this second and final part, we will proceed to abstract a WordPress application, making its code ready to be used with Symfony components, Laravel framework, and October CMS (which is based on Laravel).

Accessing Services

Before we start abstracting the code, we need to provide the layer of dependency injection to the application. As described in the first part of this series, this layer is satisfied through Symfony’s DependencyInjection component. To access the defined services, we create a class ContainerBuilderFactory which simply stores a static instance of the component’s ContainerBuilder object:

use SymfonyComponentDependencyInjectionContainerBuilder;

class ContainerBuilderFactory {
  private static $instance;
  public static function init()
    self::$instance = new ContainerBuilder();
  public static function getInstance()
    return self::$instance;

Then, to access a service called "cache", the application requests it like this:

$cacheService = ContainerBuilderFactory::getInstance()->get('cache');
// Do something with the service
// $cacheService->...

Abstracting WordPress Code

We have identified the following pieces of code and concepts from a WordPress application that need be abstracted away from WordPress’s opinionatedness:

  • accessing functions
  • function names
  • function parameters
  • states (and other constant values)
  • CMS helper functions
  • user permissions
  • application options
  • database column names
  • errors
  • hooks
  • routing
  • object properties
  • global state
  • entity models (meta, post types, pages being posts, and taxonomies —tags and categories—)
  • translation
  • media.

Let’s proceed to abstract them, one by one.

Note: For ease of reading, I have omitted adding namespaces to all classes and interfaces throughout this article. However, adding namespaces, as specified in PHP Standards Recommendation PSR-4, is a must! Among other advantages, the application can then benefit from autoloading, and Symfony’s dependency injection can rely on automatic service loading as to reduce its configuration to the bare minimum.

Accessing functions

The mantra “code against interfaces, not implementations” means that all those functions provided by the CMS cannot be accessed directly anymore. Instead, we must access the function from a contract (an interface), on which the CMS function will simply be the implementation. By the end of the abstraction, since no WordPress code will be referenced directly anymore, we can then swap WordPress with a different CMS.

For instance, if our application accesses function get_posts:

$posts = get_posts($args);

We must then abstract this function under some contract:

interface PostAPIInterface
  public function getPosts($args);

The contract must be implemented for WordPress:

class WPPostAPI implements PostAPIInterface
  public function getPosts($args) {
    return get_posts($args);

A service "posts_api" must be added to the dependency injection services.yaml configuration file, indicating which class resolves the service:

    class: WPPostAPI

And finally, the application can reference the function through service "posts_api":

$postsAPIService = ContainerBuilderFactory::getInstance()->get('posts_api');
$posts = $postsAPIService->getPosts($args);

Function names

If you have noticed from the code demonstrated above, function get_posts is abstracted as getPosts. There are a couple of reasons why this is a good idea:

  • By calling the function differently, it helps identify which code belongs to WordPress and which code belongs to our abstracted application.
  • Function names must be camelCased to comply with PSR-2, which attempts to define a standard for writing PHP code.

Certain functions can be redefined, making more sense in an abstract context. For instance, WordPress function get_user_by($field, $value) uses parameter $field with values "id", "ID", "slug", "email" or "login" to know how to get the user. Instead of replicating this methodology, we can explicitly define a separate function for each of them:

interface UsersAPIInterface
  public function getUserById($value);
  public function getUserByEmail($value);
  public function getUserBySlug($value);
  public function getUserByLogin($value);

And these are resolved for WordPress:

class WPUsersAPI implements UsersAPIInterface
  public function getUserById($value)
    return get_user_by('id', $value);
  public function getUserByEmail($value)
    return get_user_by('email', $value);
  public function getUserBySlug($value)
    return get_user_by('slug', $value);
  public function getUserByLogin($value)
    return get_user_by('login', $value);

Certain other functions should be renamed because their names convey information about their implementation, which may not apply for a different CMS. For instance, WordPress function get_the_author_meta can receive parameter "user_lastname", indicating that the user’s lastname is stored as a “meta” value (which is defined as an additional property for an object, not originally mapped in the database model). However, other CMSs may have a column "lastname" in the user table, so it doesn’t apply as a meta value. (The actual definition of “meta” value is actually inconsistent in WordPress: function get_the_author_meta also accepts value "user_email", even though the email is stored on the user table. Hence, I’d rather stick to my definition of “meta” value, and remove all inconsistencies from the abstracted code.)

Then, our contract will implement the following functions:

interface UsersAPIInterface
  public function getUserDisplayName($user_id);
  public function getUserEmail($user_id);
  public function getUserFirstname($user_id);
  public function getUserLastname($user_id);

Which are resolved for WordPress:

class WPUsersAPI implements UsersAPIInterface
  public function getUserDisplayName($user_id)
    return get_the_author_meta('display_name', $user_id);
  public function getUserEmail($user_id)
    return get_the_author_meta('user_email', $user_id);
  public function getUserFirstname($user_id)
    return get_the_author_meta('user_firstname', $user_id);
  public function getUserLastname($user_id)
    return get_the_author_meta('user_lastname', $user_id);

Our functions could also be re-defined as to remove the limitations from WordPress. For instance, function update_user_meta($user_id, $meta_key, $meta_value) can receive one meta attribute at a time, which makes sense since each of these is updated on its own database query. However, October CMS maps all meta attributes together on a single database column, so it makes more sense to update all values together on a single database operation. Then, our contract can include an operation updateUserMetaAttributes($user_id, $meta) which can update several meta values at the same time:

interface UserMetaInterface
  public function updateUserMetaAttributes($user_id, $meta);

Which is resolved for WordPress like this:

class WPUsersAPI implements UsersAPIInterface
  public function updateUserMetaAttributes($user_id, $meta)
    foreach ($meta as $meta_key => $meta_value) {
      update_user_meta($user_id, $meta_key, $meta_value);

Finally, we may want to re-define a function to remove its ambiguities. For instance, WordPress function add_query_arg can receive parameters in two different ways:

  1. Using a single key and value: add_query_arg('key', 'value', '');
  2. Using an associative array: add_query_arg(['key1' => 'value1', 'key2' => 'value2'], '');

This becomes difficult to keep consistent across CMSs. Hence, our contract can define functions addQueryArg (singular) and addQueryArgs (plural) as to remove the ambiguity:

public function addQueryArg(string $key, string $value, string $url);
public function addQueryArgs(array $key_values, string $url);

Function parameters

We must also abstract the parameters to the function, making sure they make sense in a generic context. For each function to abstract, we must consider:

  • renaming and/or re-defining the parameters;
  • renaming and/or re-defining the attributes passed on array parameters.

For instance, WordPress function get_posts receives a unique parameter $args, which is an array of attributes. One of its attributes is fields which, when given the value "ids", makes the function return an array of IDs instead of an array of objects. However, I deem this implementation too specific for WordPress, and for a generic context I’d prefer a different solution: Convey this information through a separate parameter called $options, under attribute "return-type".

To accomplish this, we add parameter $options to the function in our contract:

interface PostAPIInterface
  public function getPosts($args, $options = []);

Instead of referencing WordPress constant value "ids" (which we can’t guarantee will be the one used in all other CMSs), we create a corresponding constant value for our abstracted application:

class Constants
  const RETURNTYPE_IDS = 'ids';

The WordPress implementation must map and recreate the parameters between the contract and the implementation:

class WPPostAPI implements PostAPIInterface
  public function getPosts($args, $options = []) {
    if ($options['return-type'] == Constants::RETURNTYPE_IDS) {
      $args['fields'] = 'ids';
    return get_posts($args);

And finally, we can execute the code through our contract:

$options = [
  'return-type' => Constants::RETURNTYPE_IDS,
$post_ids = $postsAPIService->getPosts($args, $options);

While abstracting the parameters, we should avoid transferring WordPress’s technical debt to our abstracted code, whenever possible. For instance, parameter $args from function get_posts can contain attribute 'post_type'. This attribute name is somewhat misleading, since it can receive one element (post_type => "post") but also a list of them (post_type => "post, event"), so this name should be in plural instead: post_types. When abstracting this piece of code, we can set our interface to expect attribute post_types instead, which will be mapped to WordPress’s post_type.

Similarly, different functions accept arguments with different names, even though these have the same objective, so their names can be unified. For instance, through parameter $args, WordPress function get_posts accepts attribute posts_per_page, and function get_users accepts attribute number. These attribute names can perfectly be replaced with the more generic attribute name limit.

It is also a good idea to rename parameters to make it easy to understand which ones belong to WordPress and which ones have been abstracted. For instance, we can decide to replace all "_" with "-", so our newly-defined argument post_types becomes post-types.

Applying these prior considerations, our abstracted code will look like this:

class WPPostAPI implements PostAPIInterface
  public function getPosts($args, $options = []) {
    if (isset($args['post-types'])) {
      $args['post_type'] = $args['post-types'];
    if (isset($args['limit'])) { 
      $args['posts_per_page'] = $args['limit'];
    return get_posts($args);

We can also re-define attributes to modify the shape of their values. For instance, WordPress parameter $args in function get_posts can receive attribute date_query, whose properties ("after", "inclusive", etc) can be considered specific to WordPress:

$date = current_time('timestamp');
$args['date_query'] = array(
    'after' => date('Y-m-d H:i:s', $date),
    'inclusive' => true,

To unify the shape of this value into something more generic, we can re-implement it using other arguments, such as "date-from" and "date-from-inclusive" (this solution is not 100% convincing though, since it is more verbose than WordPress’s):

class WPPostAPI implements PostAPIInterface
  public function getPosts($args, $options = []) {
    if (isset($args['date-from'])) {
      $args['date_args'][] = [
        'after' => $args['date-from'],
        'inclusive' => false,
    if (isset($args['date-from-inclusive'])) {
      $args['date_args'][] = [
        'after' => $args['date-from-inclusive'],
        'inclusive' => true,
    return get_posts($args);

In addition, we need to consider if to abstract or not those parameters which are too specific to WordPress. For instance, function get_posts allows to order posts by attribute menu_order, which I don’t think it works in a generic context. Then, I’d rather not abstract this code and keep it on the CMS-specific package for WordPress.

Finally, we can also add argument types (and, since here we are, also return types) to our contract fuction, making it more understandable and allowing the code to fail in compilation time instead of during runtime:

interface PostAPIInterface
  public function getPosts(array $args, array $options = []): array;

States (and other constant values)

We need to make sure that all states have the same meaning in all CMSs. For instance, posts in WordPress can have one among the following states: "publish", "pending", "draft" or "trash". To make sure that the application references the abstracted version of the states and not the CMS-specific one, we can simply define a constant value for each of them:

class PostStates {
  const PUBLISHED = 'published';
  const PENDING = 'pending';
  const DRAFT = 'draft';
  const TRASH = 'trash';

As it can be seen, the actual constant values may or may not be the same as in WordPress: while "publish" was renamed as "published", the other ones remain the same.

For the implementation for WordPress, we convert from the agnostic value to the WordPress-specific one:

class WPPostAPI implements PostAPIInterface
  public function getPosts($args, $options = []) {
    if (isset($args['post-status'])) {
      $conversion = [
        PostStates::PUBLISHED => 'publish',
        PostStates::PENDING => 'pending',
        PostStates::DRAFT => 'draft',
        PostStates::TRASH => 'trash',
      $args['post_status'] = $conversion[$args['post-status']];
    return get_posts($args);

Finally, we can reference these constants throughout our CMS-agnostic application:

$args = [
  'post-status' => PostStates::PUBLISHED,
$posts = $postsAPIService->getPosts($args);

This strategy works under the assumption that all CMSs will support these states. If any CMS does not support a particular state (eg: "pending") then it should throw an exception whenever a corresponding functionality is invoked.

CMS helper functions

WordPress implements several helper functions that must also abstracted, such as make_clickable. Because these functions are very generic, we can implement a default behavior for them that works well in an abstract context, and which can be overridden if the CMS implements a better solution.

We first define the contract:

interface HelperAPIInterface
  public function makeClickable(string $text);

And provide a default behaviour for the helper functions through an abstract class:

abstract class AbstractHelperAPI implements HelperAPIInterface
  public function makeClickable(string $text) {
    return preg_replace('!(((f|ht)tp(s)?://)[-a-zA-Zа-яА-Я()0-9@:%_ .~#?&;//=] )!i', '$1', $text);

Now, our application can either use this functionality or, if it runs on WordPress, use the WordPress-specific implementation:

class WPHelperAPI extends AbstractHelperAPI
  public function makeClickable(string $text) {
    return make_clickable($text);

User permissions

For all CMSs which support user management, in addition to abstracting the corresponding functions (such as current_user_can and user_can in WordPress), we must also make sure that the user permissions (or capabilities) have the same effect across all CMSs. To achieve this, our abstracted application needs to explicitly state what is expected from the capability, and the implementation for each CMS must either satisfy it through one of its own capabilities or throw an exception if it can’t satisfy it. For instance, if the application needs to validate if the user can edit posts, it can represent it through a capability called "capability:editPosts", which is satisfied for WordPress through its capability "edit_posts".

This is still an instance of the “code against interfaces, not implementations” principle, however here we run against a problem: Whereas in PHP we can define interfaces and classes to model contracts and service providers (which works in compilation time, so that the code doesn’t compile if a class implementing an interface does not implement all functions defined in the interface), PHP offers no similar construct to validate that a contract capability (which is simply a string, such as "capability:editPosts") has been satisfied through a capability by the CMS. This concept, which I call a “loose contract”, will need to be handled by our application, on runtime.

To deal with “loose contracts”, I have created a service LooseContractService through which:

  • the application can define what “contract names” must be implemented, through function requireNames.
  • the CMS-specific implementations can satisfy those names, through function implementNames.
  • the application can get the implementation of a name through function getImplementedName.
  • the application can also inquire for all non-satisfied required names through function getNotImplementedRequiredNames, as to throw an exception or log the error if needed.

The service looks like this:

class LooseContractService
  protected $requiredNames = [];
  protected $nameImplementations = [];

  public function requireNames(array $names): void
    $this->requiredNames = array_merge(

  public function implementNames(array $nameImplementations): void
    $this->nameImplementations = array_merge(

  public function getImplementedName(string $name): ?string {
    return $this->nameImplementations[$name];

  public function getNotImplementedRequiredNames(): array {
    return array_diff(

The application, when initialized, can then establish loose contracts by requiring names:

$looseContractService = ContainerBuilderFactory::getInstance()->get('loose_contracts');

And the CMS-specific implementation can satisfy these:

  'capability:editPosts' => 'edit_posts',

The application can then resolve the required name to the implementation from the CMS. If this required name (in this case, a capability) is not implemented, then the application may throw an exception:

$cmsCapabilityName = $looseContractService->getImplementedName('capability:editPosts');
if (!$cmsCapabilityName) {
  throw new Exception(sprintf(
    "The CMS has no support for capability "%s"",
// Now can use the capability to check for permissions
$userManagementAPIService = ContainerBuilderFactory::getInstance()->get('user_management_api');
if ($userManagementAPIService->userCan($user_id, $cmsCapabilityName)) {

Alternatively, the application can also fail when first initialized if any one required name is not satisfied:

if ($notImplementedNames = $looseContractService->getNotImplementedRequiredNames()) {
  throw new Exception(sprintf(
    "The CMS has not implemented loose contract names %s",
    implode(', ', $notImplementedNames)

Application options

WordPress ships with several application options, such as those stored in table wp_options under entries "blogname", "blogdescription", "admin_email", "date_format" and many others. Abstracting application options involves:

  • abstraction the function getOption;
  • abstracting each of the required options, aiming to make the CMS satisfy the notion of this option (eg: if a CMS doesn’t have an option for the site’s description, it can’t return the site’s name instead).

Let’s solve these 2 actions in turn. Concerning function getOption, I believe that we can expect all CMSs to support storing and retrieving options, so we can place the corresponding function under a CMSCoreInterface contract:

interface CMSCoreInterface
  public function getOption($option, $default = false);

As it can be observed from the function signature above, I’m making the assumption that each option will also have a default value. However, I don’t know if every CMS allows setting default values for options. But it doesn’t matter since the implementation can simply return NULL then.

This function is resolved for WordPress like this:

class WPCMSCore implements CMSCoreInterface
  public function getOption($option, $default = false)
    return get_option($option, $default);

To solve the 2nd action, which is abstracting each needed option, it is important to notice that even though we can always expect the CMS to support getOption, we can’t expect it to implement each single option used by WordPress, such as "use_smiles" or "default_ping_status". Hence, we must first filter all options, and abstract only those that make sense in a generic context, such as "siteName" or "dateFormat".

Then, having the list of options to abstract, we can use a “loose contract” (as explained earlier on) and require a corresponding option name for each, such as "option:siteName" (resolved for WordPress as "blogname") or "option:dateFormat" (resolved as "date_format").

Database column names

In WordPress, when we are requesting data from function get_posts we can set attribute "orderby" in $args to order the results, which can be based on a column from the posts table (such as values "ID", "title", "date", "comment_count", etc), a meta value (through values "meta_value" and "meta_value_num") or other values (such as "post__in" and "rand").

Whenever the value corresponds to the table column name, we can abstract them using a “loose contract”, as explained earlier on. Then, the application can reference a loose contract name:

$args = [
  'orderby' => $looseContractService->getImplementedName('dbcolumn:orderby:posts:date'),
$posts = $postsAPIService->getPosts($args);

And this name is resolved for WordPress:

  'dbcolumn:orderby:posts:date' => 'date',

Now, let’s say that in our WordPress application we have created a meta value "likes_count" (which stores how many likes a post has) to order posts by popularity, and we want to abstract this functionality too. To order results by some meta property, WordPress expects an additional attribute "meta_key", like this:

$args = [
  'orderby' => 'meta_value',
  'meta_key' => 'likes_count',

Because of this additional attribute, I consider this implementation WordPress-specific and very difficult to abstract to make it work everywhere. Then, instead of generalizing this functionality, I can simply expect every CMS to add their own, specific implementation.

Let’s do that. First, I create a helper class to retrieve the CMS-agnostic query:

class QueryHelper
  public function getOrderByQuery()
    return array(
      'orderby' => $looseContractService->getImplementedName('dbcolumn:orderby:posts:likesCount'),

The OctoberCMS-specific package can add a column "likes_count" to the posts table, and resolve name "dbcolumn:orderby:posts:likesCount" to "like_count" and it will work. The WordPress-specific package, though, must resolve "dbcolumn:orderby:posts:likesCount" as "meta_value" and then override the helper function to add the additional property "meta_key":

class WPQueryHelper extends QueryHelper
  public function getOrderByQuery()
    $query = parent::getOrderByQuery();
    $query['meta_key'] = 'likes_count';
    return $query;

Finally, we set-up the helper query class as a service in the ContainerBuilder, configure it to be resolved to the WordPress-specific class, and we obtain the query for ordering results:

$queryHelperService = ContainerBuilderFactory::getInstance()->get('query_helper');
$args = $queryHelperService->getOrderByQuery();
$posts = $postsAPIService->getPosts($args);

Abstracting the values for ordering results that do not correspond to column names or meta properties (such as "post__in" and "rand") seems to be more difficult. Because my application doesn’t use them, I haven’t considered how to do it, or even if it is possible. Then I took the easy way out: I have considered these to be WordPress-specific, hence the application makes them available only when running on WordPress.


When dealing with errors, we must consider abstracting the following elements:

  • the definition of an error;
  • error codes and messages.

Let’s review these in turn.

Definition of an error:

An Error is a special object, different than an Exception, used to indicate that some operation has failed, and why it failed. WordPress represents errors through class WP_Error, and allows to check if some returned value is an error through function is_wp_error.

We can abstract checking for an error:

interface CMSCoreInterface
  public function isError($object);

Which is resolved for WordPress like this:

class WPCMSCore implements CMSCoreInterface
  public function isError($object)
    return is_wp_error($object);

However, to deal with errors in our abstracted code, we can’t expect all CMSs to have an error class with the same properties and methods as WordPress’s WP_Error class. Hence, we must abstract this class too, and convert from the CMS error to the abstracted error after executing a function from the CMS.

The abstract error class Error is simply a slightly modified version from WordPress’s WP_Error class:

class Error {

  protected $errors = array();
  protected $error_data = array();

  public function __construct($code = null, $message = null, $data = null) 
    if ($code) {
      $this->errors[$code][] = $message;
      if ($data) {
        $this->error_data[$code] = $data;

  public function getErrorCodes()
    return array_keys($this->errors);

  public function getErrorCode()
    if ($codes = $this->getErrorCodes()) {
      return $codes[0];

    return null;

  public function getErrorMessages($code = null)
    if ($code) {
      return $this->errors[$code] ?? [];

    // Return all messages if no code specified.
    return array_reduce($this->errors, 'array_merge', array());

  public function getErrorMessage($code = null)
    if (!$code) {
      $code = $this->getErrorCode();
    $messages = $this->getErrorMessages($code);
    return $messages[0] ?? '';

  public function getErrorData($code = null)
    if (!$code) {
      $code = $this->getErrorCode();

    return $this->error_data[$code];

  public function add($code, $message, $data = null)
    $this->errors[$code][] = $message;
    if ($data) {
      $this->error_data[$code] = $data;

  public function addData($data, $code = null)
    if (!$code) {
      $code = $this->getErrorCode();

    $this->error_data[$code] = $data;

  public function remove($code)

We implement a function to convert from the CMS to the abstract error through a helper class:

class WPHelpers
  public static function returnResultOrConvertError($result)
    if (is_wp_error($result)) {
      // Create a new instance of the abstracted error class
      $error = new Error();
      foreach ($result->get_error_codes() as $code) {
        $error->add($code, $result->get_error_message($code), $result->get_error_data($code));
      return $error;
    return $result;

And we finally invoke this method for all functions that may return an error:

class UserManagementService implements UserManagementInterface
  public function getPasswordResetKey($user_id)
    $result = get_password_reset_key($user_id);
    return WPHelpers::returnResultOrConvertError($result);
Error codes and messages:

Every CMS will have its own set of error codes and corresponding explanatory messages. For instance, WordPress function get_password_reset_key can fail due to the following reasons, as represented by their error codes and messages:

  1. "no_password_reset": Password reset is not allowed for this user.
  2. "no_password_key_update": Could not save password reset key to database.

In order to unify errors so that an error code and message is consistent across CMSs, we will need to inspect these and replace them with our custom ones (possibly in function returnResultOrConvertError explained above).


Abstracting hooks involves:

  • the hook functionality;
  • the hooks themselves.

Let’s analyze these in turn.

Abstracting the hook functionality

WordPress offers the concept of “hooks”: a mechanism through which we can change a default behavior or value (through “filters”) and execute related functionality (through “actions”). Both Symfony and Laravel offer mechanisms somewhat related to hooks: Symfony provides an event dispatcher component, and Laravel’s mechanism is called events; these 2 mechanisms are similar, sending notifications of events that have already taken place, to be processed by the application through listeners.

When comparing these 3 mechanisms (hooks, event dispatcher and events) we find that WordPress’s solution is the simpler one to set-up and use: Whereas WordPress hooks enable to pass an unlimited number of parameters in the hook itself and to directly modify a value as a response from a filter, Symfony’s component requires to instantiate a new object to pass additional information, and Laravel’s solution suggests to run a command in Artisan (Laravel’s CLI) to generate the files containing the event and listener objects. If all we desire is to modify some value in the application, executing a hook such as $value = apply_filters("modifyValue", $value, $post_id); is as simple as it can get.

In the first part of this series, I explained that the CMS-agnostic application already establishes a particular solution for dependency injection instead of relying on the solution by the CMS, because the application itself needs this functionality to glue its parts together. Something similar happens with hooks: they are such a powerful concept that the application can greatly benefit by making it available to the different CMS-agnostic packages (allowing them to interact with each other) and not leave this wiring-up to be implemented only at the CMS level. Hence, I have decided to already ship a solution for the “hook” concept in the CMS-agnostic application, and this solution is the one implemented by WordPress.

In order to decouple the CMS-agnostic hooks from those from WordPress, once again we must “code against interfaces, not implementations”: We define a contract with the corresponding hook functions:

interface HooksAPIInterface
  public function addFilter(string $tag, $function_to_add, int $priority = 10, int $accepted_args = 1): void;
  public function removeFilter(string $tag, $function_to_remove, int $priority = 10): bool;
  public function applyFilters(string $tag, $value, ...$args);
  public function addAction(string $tag, $function_to_add, int $priority = 10, int $accepted_args = 1): void;
  public function removeAction(string $tag, $function_to_remove, int $priority = 10): bool;
  public function doAction(string $tag, ...$args): void;

Please notice that functions applyFilters and doAction are variadic, i.e. they can receive a variable amount of arguments through parameter ...$args. By combining this feature (which was added to PHP in version 5.6, hence it was unavailable to WordPress until very recently) with argument unpacking, i.e. passing a variable amount of parameters ...$args to a function, we can easily provide the implementation for WordPress:

class WPHooksAPI implements HooksAPIInterface
  public function addFilter(string $tag, $function_to_add, int $priority = 10, int $accepted_args = 1): void
    add_filter($tag, $function_to_add, $priority, $accepted_args);

  public function removeFilter(string $tag, $function_to_remove, int $priority = 10): bool
    return remove_filter($tag, $function_to_remove, $priority);

  public function applyFilters(string $tag, $value, ...$args)
    return apply_filters($tag, $value, ...$args);

  public function addAction(string $tag, $function_to_add, int $priority = 10, int $accepted_args = 1): void
    add_action($tag, $function_to_add, $priority, $accepted_args);

  public function removeAction(string $tag, $function_to_remove, int $priority = 10): bool
    return remove_action($tag, $function_to_remove, $priority);

  public function doAction(string $tag, ...$args): void
    do_action($tag, ...$args);

As for an application running on Symfony or Laravel, this contract can be satisfied by installing a CMS-agnostic package implementing WordPress-like hooks, such as this one, this one or this one.

Finally, whenever we need to execute a hook, we do it through the corresponding service:

$hooksAPIService = ContainerBuilderFactory::getInstance()->get('hooks_api');
$title = $hooksAPIService->applyFilters("modifyTitle", $title, $post_id);
Abstracting the hooks themselves

We need to make sure that, whenever a hook is executed, a consistent action will be executed no matter which is the CMS. For hooks defined inside of our application that is no problem, since we can resolve them ourselves, most likely in our CMS-agnostic package. However, when the hook is provided by the CMS, such as action "init" (triggered when the system has been initialized) or filter "the_title" (triggered to modify a post’s title) in WordPress, and we invoke these hooks, we must make sure that all other CMSs will process them correctly and consistently. (Please notice that this concerns hooks that make sense in every CMS, such as "init"; certain other hooks can be considered too specific to WordPress, such as filter "rest_{$this->post_type}_query" from a REST controller, so we don’t need to abstract them.)

The solution I found is to hook into actions or filters defined exclusively in the application (i.e. not in the CMS), and to bridge from CMS hooks to application hooks whenever needed. For instance, instead of adding an action for hook "init" (as defined in WordPress), any code in our application must add an action on hook "cms:init", and then we implement the bridge in the WordPress-specific package from "init" to "cms:init":

$hooksAPIService->addAction('init', function() use($hooksAPIService) {

Finally, the application can add a “loose contract” name for "cms:init", and the CMS-specific package must implement it (as demonstrated earlier on).


Different frameworks will provide different solutions for routing (i.e. the mechanism of identifying how the requested URL will be handled by the application), which reflect the architecture of the framework:

  • In WordPress, URLs map to database queries, not to routes.
  • Symfony provides a Routing component which is independent (any PHP application can install it and use it), and which enables to define custom routes and which controller will process them.
  • Laravel’s routing builds on top of Symfony’s routing component to adapt it to the Laravel framework.

As it can be seen, WordPress’s solution is the outlier here: the concept of mapping URLs to database queries is tightly coupled to WordPress’s architecture, and we would not want to restrict our abstracted application to this methodology (for instance, October CMS can be set-up as a flat-file CMS, in which case it doesn’t use a database). Instead, it makes more sense to use Symfony’s approach as its default behavior, and allow WordPress to override this behavior with its own routing mechanism.

(Indeed, while WordPress’s approach works well for retrieving content, it is rather inappropriate when we need to access some functionality, such as displaying a contact form. In this case, before the launch of Gutenberg, we were forced to create a page and add a shortcode "[contact_form]" to it as content, which is not as clean as simply mapping the route to its corresponding controller directly.)

Hence, the routing for our abstracted application will not be based around the modeled entities (post, page, category, tag, author) but purely on custom-defined routes. This should already work perfectly for Symfony and Laravel, using their own solutions, and there is not much for us to do other than injecting the routes with the corresponding controllers into the application’s configuration.

To make it work in WordPress, though, we need to take some extra steps: We must introduce an external library to handle routing, such as Cortex. Making use of Cortex, the application running on WordPress can have it both ways:

  • if there is a custom-defined route matching the requested URL, use its corresponding controller.
  • if not, let WordPress handle the request in its own way (i.e. retrieving the matched database entity or returning a 404 if no match is successful).

To implement this functionality, I have designed the contract CMSRoutingInterface to, given the requested URL, calculate two pieces of information:

  • the actual route, such as contact, posts or posts/my-first-post.
  • the nature of the route: core nature values "standard", "home" and "404", and additional nature values added through packages such as "post" through a “Posts” package or "user" through a “Users” package.

The nature of the route is an artificial construction that enables the CMS-agnostic application to identify if the route has extra qualities attached to it. For instance, when requesting the URL for a single post in WordPress, the corresponding database object post is loaded into the global state, under global $post. It also helps identify which case we want to handle, to avoid inconsistencies. For instance, we could have defined a custom route contact handled by a controller, which will have nature "standard", and also a page in WordPress with slug "contact", which will have nature "page" (added through a package called “Pages”). Then, our application can prioritize which way to handle the request, either through the controller or through a database query.

Let’s implement it. We first define the service’s contract:

interface CMSRoutingInterface
  public function getNature();
  public function getRoute();

We can then define an abstract class which provides a base implementation of these functions:

abstract class AbstractCMSRouting implements CMSRoutingInterface
  const NATURE_STANDARD = 'standard';
  const NATURE_HOME = 'home';
  const NATURE_404 = '404';

  public function getNature()
    return self::NATURE_STANDARD;

  public function getRoute()
    // By default, the URI path is already the route (minus parameters and trailing slashes)
    $route = $_SERVER['REQUEST_URI'];
    $params_pos = strpos($route, '?');
    if ($params_pos !== false) {
       $route = substr($route, 0, $params_pos);
    return trim($route, '/');

And the implementation is overriden for WordPress:

class WPCMSRouting extends AbstractCMSRouting
  const ROUTE_QUERY = [
    'custom_route_key' => 'custom_route_value',
  private $query;
  private function init()
    if (is_null($this->query)) {
      global $wp_query;
      $this->query = $wp_query;

  private function isStandardRoute() {
    return !empty(array_intersect($this->query->query_vars, self::ROUTE_QUERY));

  public function getNature()
    if ($this->isStandardRoute()) {
      return self::NATURE_STANDARD;
    } elseif ($this->query->is_home() || $this->query->is_front_page()) {
      return self::NATURE_HOME;
    } elseif ($this->query->is_404()) {
      return self::NATURE_404;

    // Allow components to implement their own natures
    $hooksAPIService = ContainerBuilderFactory::getInstance()->get('hooks_api');
    return $hooksAPIService->applyFilters(

In the code above, please notice how constant ROUTE_QUERY is used by the service to know if the route is a custom-defined one, as configured through Cortex:

  function(RouteCollectionInterface $routes) {  
    // Hook into filter "routes" to provide custom-defined routes
    $appRoutes = $hooksAPIService->applyFilters("routes", []);
    foreach ($appRoutes as $route) {
      $routes->addRoute(new QueryRoute(
        function (array $matches) {
          return WPCMSRouting::ROUTE_QUERY;

Finally, we add our routes through hook "routes":

  function($routes) {
    return array_merge(

Now, the application can find out the route and its nature, and proceed accordingly (for instance, for a "standard" nature invoke its controller, or for a "post" nature invoke WordPress’s templating system):

$cmsRoutingService = ContainerBuilderFactory::getInstance()->get('routing');
$nature = $cmsRoutingService->getNature();
$route = $cmsRoutingService->getRoute();
// Process the requested route, as appropriate
// ...

Object properties

A rather inconvenient consequence of abstracting our code is that we can’t reference the properties from an object directly, and we must do it through a function instead. This is because different CMSs will represent the same object as containing different properties, and it is easier to abstract a function to access the object properties than to abstract the object itself (in which case, among other disadvantages, we may have to reproduce the object caching mechanism from the CMS). For instance, a post object $post contains its ID under $post->ID in WordPress and under $post->id in October CMS. To resolve this property, our contract PostObjectPropertyResolverInterface will contain function getId:

interface PostObjectPropertyResolverInterface {
  public function getId($post);

Which is resolved for WordPress like this:

class WPPostObjectPropertyResolver implements PostObjectPropertyResolverInterface {
  public function getId($post)
    return $post->ID;

Similarly, the post content property is $post->post_content in WordPress and $post->content in October CMS. Our contract will then allow to access this property through function getContent:

interface PostObjectPropertyResolverInterface {
  public function getContent($post);

Which is resolved for WordPress like this:

class WPPostObjectPropertyResolver implements PostObjectPropertyResolverInterface {
  public function getContent($post)
    return $post->post_content;

Please notice that function getContent receives the object itself through parameter $post. This is because we are assuming the content will be a property of the post object in all CMSs. However, we should be cautious on making this assumption, and decide on a property by property basis. If we don’t want to make the previous assumption, then it makes more sense for function getContent to receive the post’s ID instead:

interface PostObjectPropertyResolverInterface {
  public function getContent($post_id);

Being more conservative, the latter function signature makes the code potentially more reusable, however it is also less efficient, because the implementation will still need to retrieve the post object:

class WPPostObjectPropertyResolver implements PostObjectPropertyResolverInterface {
  public function getContent($post_id)
    $post = get_post($post_id);
    return $post->post_content;

In addition, some properties may be needed in their original value and also after applying some processing; for these cases, we will need to implement a corresponding extra function in our contract. For instance, the post content needs be accessed also as HTML, which is done through executing apply_filters('the_content', $post->post_content) in WordPress, or directly through property $post->content_html in October CMS. Hence, our contract may have 2 functions to resolve the content property:

interface PostObjectPropertyResolverInterface {
  public function getContent($post_id); // = raw content
  public function getHTMLContent($post_id);

We must also be concerned with abstracting the value that the property can have. For instance, a comment is approved in WordPress if its property comment_approved has the value "1". However, other CMSs may have a similar property with value true. Hence, the contract should remove any potential inconsistency or ambiguity:

interface CommentObjectPropertyResolverInterface {
  public function isApproved($comment);

Which is implemented for WordPress like this:

class WPCommentObjectPropertyResolver implements CommentObjectPropertyResolverInterface {
  public function isApproved($comment)
    return $comment->comment_approved == "1";

Global state

WordPress sets several variables in the global context, such as global $post when querying a single post. Keeping variables in the global context is considered an anti-pattern, since the developer could unintentionally override their values, producing bugs that are difficult to track down. Hence, abstracting our code gives us the chance to implement a better solution.

An approach we can take is to create a corresponding class AppState which simply contains a property to store all variables that our application will need. In addition to initializing all core variables, we enable components to initialize their own ones through hooks:

class AppState
  public static $vars = [];

  public static function getVars()
    return self::$vars;

  public static function initialize()
    // Initialize core variables
    self::$vars['nature'] = $cmsRoutingService->getNature();
    self::$vars['route'] = $cmsRoutingService->getRoute();

    // Initialize $vars through hooks
    self::$vars = $hooksAPIService->applyFilters("AppState:init", self::$vars);

    return self::$vars;

To replace global $post, a hook from WordPress can then set this data through a hook. A first step would be to set the data under "post-id":

  function($vars) {
    if (is_single()) {
      global $post;
      $vars['post-id'] => $post->ID;
    return $vars;

However, we can also abstract the global variables: instead of dealing with fixed entities (such as posts, users, comments, etc), we can deal with the entity in a generic way through "object-id", and we obtain its properties by inquiring the nature of the requested route:

  function($vars) {
    if ($vars['nature'] == 'post') {
      global $post;
      $vars['object-id'] => $post->ID;
    return $vars;

From now own, if we need to display a property of the current post, we access it from the newly defined class instead of the global context:

$vars = AppState::getVars();
$object_id = $vars['object-id'];
// Do something with it
// ...

Entity models (meta, post types, pages being posts, and taxonomies —tags and categories—)

We must abstract those decisions made for WordPress concerning how its entities are modeled. Whenever we consider that WordPress’s opinionatedness makes sense in a generic context too, we can then replicate such a decision for our CMS-agnostic code.


As mentioned earlier, the concept of “meta” must be decoupled from the model entity (such as “post meta” from “posts”), so if a CMS doesn’t provide support for meta, it can then discard only this functionality.

Then, package “Post Meta” (decoupled from, but dependent on, package “Posts”) defines the following contract:

interface PostMetaAPIInterface
  public function getMetaKey($meta_key);
  public function getPostMeta($post_id, $key, $single = false);
  public function deletePostMeta($post_id, $meta_key, $meta_value = '');
  public function addPostMeta($post_id, $meta_key, $meta_value, $unique = false);
  public function updatePostMeta($post_id, $meta_key, $meta_value);

Which is resolved for WordPress like this:

class WPPostMetaAPI implements PostMetaAPIInterface
  public function getMetaKey($meta_key)
    return '_'.$meta_key;
  public function getPostMeta($post_id, $key, $single = false)
    return get_post_meta($post_id, $key, $single);
  public function deletePostMeta($post_id, $meta_key, $meta_value = '')
    return delete_post_meta($post_id, $meta_key, $meta_value);
  public function addPostMeta($post_id, $meta_key, $meta_value, $unique = false)
    return add_post_meta($post_id, $meta_key, $meta_value, $unique);
  public function updatePostMeta($post_id, $meta_key, $meta_value)
    return update_post_meta($post_id, $meta_key, $meta_value);
Post types:

I have decided that WordPress’s concept of a custom post type, which allows to model entities (such as an event or a portfolio) as extensions of posts, can apply in a generic context, and as such, I have replicated this functionality in the CMS-agnostic code. This decision is controversial, however, I justify it because the application may need to display a feed of entries of different types (such as posts, events, etc) and custom post types make such implementation feasible. Without custom post types, I would expect the application to need to execute several queries to bring the data for every entity type, and the logic would get all muddled up (for instance, if fetching 12 entries, should we fetch 6 posts and 6 events? but what if the events were posted much earlier than the last 12 posts? and so on).

What happens when the CMS doesn’t support this concept? Well, nothing serious happens: a post will still indicate its custom post type to be a “post”, and no other entities will inherit from the post. The application will still work properly, just with some slight overhead from the unneeded code. This is a trade-off that, I believe, is more than worth it.

To support custom post types, we simply add a function getPostType in our contract:

interface PostAPIInterface
  public function getPostType($post_id);

Which is resolved for WordPress like this:

class WPPostAPI implements PostAPIInterface
  public function getPostType($post_id) {
    return get_post_type($post_id);
Pages being posts:

While I justify keeping custom post types in order to extend posts, I don’t justify a page being a post, as it happens in WordPress, because in other CMSs these entities are completely decoupled and, more importantly, a page may have higher rank than a post, so making a page extend from a post would make no sense. For instance, October CMS ships pages in its core functionality, but posts must be installed through plugins.

Hence we must create separate contracts for posts and pages, even though they may contain the same functions:

interface PostAPIInterface
  public function getTitle($post_id);

interface PageAPIInterface
  public function getTitle($page_id);

To resolve these contracts for WordPress and avoid duplicating code, we can implement the common functionality through a trait:

trait WPCommonPostFunctions
  public function getTitle($post_id)
    return get_the_title($post_id);

class WPPostAPI implements PostAPIInterface
  use WPCommonPostFunctions;

class WPPageAPI implements PageAPIInterface
  use WPCommonPostFunctions;
Taxonomies (tags and categories):

Once again, we can’t expect all CMSs to support what is called taxonomies in WordPress: tags and categories. Hence, we must implement this functionality through a package “Taxonomies”, and, assuming that tags and categories are added to posts, make this package dependent on package “Posts”.

interface TaxonomyAPIInterface
  public function getPostCategories($post_id, $options = []);
  public function getPostTags($post_id, $options = []);
  public function getCategories($query, $options = []);
  public function getTags($query, $options = []);
  public function getCategory($cat_id);
  public function getTag($tag_id);

We could have decided to create two separate packages “Categories” and “Tags” instead of “Taxonomies”, however, as the implementation in WordPress makes evident, a tag and a category are basically the same concept of entity with only a tiny difference: categories are hierarchical (i.e. a category can have a parent category), but tags are not. Then, I consider that it makes sense to keep this concept for a generic context, and shipped under a single package “Taxonomies”.

We must pay attention that certain functionalities involve both posts and taxonomies, and these must be appropriately decoupled. For instance, in WordPress we can retrieve posts that were tagged "politics" by executing get_posts(['tag' => "politics"]). In this case, while function getPosts must be implemented in package “Posts”, filtering by tags must be implemented in package “Taxonomies”. To accomplish this separation, we can simply execute a hook in the implementation of function getPosts for WordPress, allowing any component to modify the arguments before executing get_posts:

class WPPostAPI implements PostAPIInterface
  public function getPosts($args) {
    $args = $hooksAPIService->applyFilters("modifyArgs", $args);
    return get_posts($args);

And finally we implement the hook in package “Taxonomies for WordPress”:

  function($args) {
    if (isset($args['tags'])) {
      $args['tag'] = implode(',', $args['tags']);
    if (isset($args['categories'])) {
      $args['cat'] = implode(',', $args['categories']);
    return $args;

Please notice that in the abstracted code the attributes were re-defined (following the recommendations for abstracting function parameters, explained earlier on): "tag" must be provided as "tags" and "cat" must be provided as "categories" (shifting the connotation from singular to plural), and these values must be passed as arrays (i.e. removed accepting comma-separated strings as in WordPress, to add consistency).


Because calls to translate strings are spread all over the application code, translation is not a functionality that we can opt out from, and we should make sure that the other frameworks are compatible with our chosen translation mechanism.

In WordPress, which implements internationalization through gettext, we are required to set-up translation files for each locale code (such as ‘fr_FR’, which is the code for french language from FRance), and these can be set under a text domain (which allows themes or plugins to define their own translations without fear of collision with the translations from other pieces of code). We don’t need to check for support for placeholders in the string to translate (such as when doing sprintf(__("Welcome %s"), $user_name)), because function sprintf belongs to PHP and not to the CMS, so it will always work.

Let’s check if the other frameworks support the required two properties, i.e. getting the translation data for a specific locale composed of language and country, and under a specific text domain:

  • Symfony’s translation component supports these two properties.
  • The locale used in Laravel’s localization involves the language but not the country, and text domains are not supported (they could be replicated through overriding package language files, but the domain is not explicitly set, so the contract and the implementation would be inconsistent with each other).

However, luckily there is library Laravel Gettext which can replace Laravel’s native implementation with Symfony’s translation component. Hence, we got support for all frameworks, and we can rely on a WordPress-like solution.

We can then define our contract mirroring the WordPress function signatures:

interface TranslationAPIInterface
  public function __($text, $domain = 'default');
  public function _e($text, $domain = 'default');

The implementation of the contract for WordPress is like this:

class WPTranslationAPI implements TranslationAPIInterface
  public function __($text, $domain = 'default')
    return __($text, $domain);
  public function _e($text, $domain = 'default')
    _e($text, $domain);

And to use it in our application, we do:

$translationAPI = ContainerBuilderFactory::getInstance()->get('translation_api');
$text = $translationAPI->__("translate this", "my-domain");


WordPress has media management as part of its core functionality, which represents a media element as an entity all by itself, and allows to manipulate the media element (such as cropping or resizing images), but we can’t expect all CMSs to have similar functionality. Hence, media management must be decoupled from the CMS core functionality.

For the corresponding contract, we can mirror the WordPress media functions, but removing WordPress’s opinionatedness. For instance, in WordPress, a media element is a post (with post type "attachment"), but for the CMS-agnostic code it is not, hence the parameter must be $media_id (or $image_id) instead of $post_id. Similarly, WordPress treats media as attachments to posts, but this doesn’t need to be the case everywhere, hence we can remove the word “attachment” from the function signatures. Finally, we can decide to keep the $size of the image in the contract; if the CMS doesn’t support creating multiple image sizes for an image, then it can just fall back on its default value NULL and nothing grave happens:

interface MediaAPIInterface
  public function getImageSrcAndDimensions($image_id, $size = null): array;
  public function getImageURL($image_id, $size = null): string;

The response by function getImageSrcAndDimensions can be asbtracted too, returning an array of our own design instead of simply re-using the one from the WordPress function wp_get_attachment_image_src:

class WPMediaAPI implements MediaAPIInterface
  public function getImageSrcAndDimensions($image_id, $size = null): array
    $img_data = wp_get_attachment_image_src($image_id, $size);
    return [
      'src' => $img_data[0],
      'width' => $img_data[1],
      'height' => $img_data[2],
  public function getImageURL($image_id, $size = null): string
    return wp_get_attachment_image_url($image_id, $size);


Setting-up a CMS-agnostic architecture for our application can be a painful endeavor. As it was demonstrated in this article, abstracting all the code was a lengthy process, taking plenty of time and energy to achieve, and it is not even finished yet. I wouldn’t be surprised if the reader is intimidated by the idea of going through this process in order to convert a WordPress application into a CMS-agnostic one. If I hadn’t done the abstraction myself, I would certainly be intimidated too.

My suggestion is for the reader is to analyze if going through this process makes sense based on a project-by-project basis. If there is no need whatsoever to port an application to a different CMS, then you will be right to stay away from this process and stick to the WordPress way. However, if you do need to migrate an application away from WordPress and want to reduce the effort required, or if you already need to maintain several codebases which would benefit from code reusability, or even if you may migrate the application sometime in the future and you have just started a new project, then this process is for you. It may be painful to implement, but well worth it. I know because I’ve been there. But I’ve survived, and I’d certainly do it again. Thanks for reading.

Smashing Editorial(dm, yk, il)



A contact form is a quick way for users to get in touch with you. Some of the benefits of a contact form include the following.

Reduce Spam

One of the ways to cut down on spam is to use a contact form. You will no longer have to put your email address out there, which makes it harder for people to send you spam mail.

Collect Specific Information

A contact form allows you to request specific information or control the information a user provides.  Since you are at liberty to add or remove any form field you wish, you can make particular fields required with a contact form.

Collect Leads

People find it easy to fill a contact form as opposed to calling or sending an email. Having a contact form is an effective way to collect leads and increase conversion rates. Even the simplest contact form can lead to an increase in leads.

Obtain Feedback

You can use a contact form to create a specific form geared towards obtaining questions and feedback from customers, especially for new products or services. This kind of information can be used to make better marketing decisions or improvements.

Obtain Quotes

You can also use a contact form to allow customers to request quotes, especially for service-oriented businesses. Or you can use it to receive quotes from customers.


A contact form provides an easy way for customers to get in touch with you. Instead of scouring through your website to obtain your email, you can place the form in an accessible page where users will find it easy to contact you.

Premium Contact Form Plugins

Free plugins are great when you’re getting started with WordPress, but if you want to go to the next level with your sites and save yourself time while you’re doing it, you should consider a premium contact form plugin from CodeCanyon.

What We’ll Be Building

This tutorial will show you how to add Google Maps to a contact form using Contact Form 7 and the Google Maps Extension for CF7 WordPress plugin. By the end of the tutorial, we should have something like this:

The completed contact form with Google Maps extension

CF7 Plugin for Free Contact Forms

Contact Form 7 provides a simple and flexible contact form for your WordPress website. You can customize the design of the form and configure where information is sent when users contact you. Contact Form 7 is very popular and hence has tons of free and paid add-ons that provide extra features such as Dropbox integration, maps integration, and so on.

The plugin comes with additional features such as AJAX submission, Akismet spam filtering, form upload files, and even the ability to add a CAPTCHA to the form. The most significant advantage of this form is that it’s free to use.

Why Use Contact Form 7?

Many plugins can help you create a contact form for your WordPress website; Contact Form 7 is one of those plugins. Since it’s flexible and easy to use, Contact Form 7 is considered the top choice when choosing a contact form.

This plugin provides a straightforward and uncomplicated way to get set up, especially if you don’t know much about coding.

Install the CF7 Contact Form

The fastest way to install the CF7 contact form plugin is to use the plugin search feature from within WordPress. Go to Plugins > Add New and search for CF7 contact form with the search bar. Click on it and click Install. After the plugin has installed, click on the Activate link to activate the plugin.

Google Maps Extension for CF7

The Google Maps Extension for CF7 provides a great way to enhance your form by adding a map field to it. This allows you to obtain the user’s location. Some of the notable features of this plugin include:

  • collect user information via Google Maps
  • visitors can drop markers or draw any number of rectangles, circles, and polygons on the map
  • automatically obtain a KML file based on the visitor’s location
  • customize Google Maps according to your needs
  • fully responsive maps
  • choose the map type, i.e. Roadmap, Satellite, Hybrid, or Terrain
  • customize attributes such as colors, shapes, thickness, stroke color, and opacity

Purchase and download the Google Maps Extension for CF7. You can find your installable WordPress files in the download section of your account.

Once you download the WordPress files, log in to your WordPress site, and install the plugin. Go to Plugins > Add New and upload the WordPress zip file you got from CodeCanyon. After uploading, click Install Now, wait a few seconds, and then click Activate. You can now start using the plugin.

Google maps are now integrated with the contact form, as shown below.

Google Maps integration in CF7


To add a map to our contact form, we need to generate a Google Maps API Key.

To obtain an API key:

  • Go to the Google Cloud Console and sign in with your Google account.
  • Select or create a new project.
  • Navigate to the Credentials page, and click Create credentials > API key
  • Copy and paste the key to your WordPress site under CF7 Google maps settings.
Getting a Google Maps API key

The Google Maps extension for CF7 provides various ways in which you can configure maps.

  • Users can mark their current location using a marker or highlight an area. They can also draw polygons, polylines, circles, and rectangles.
  • The user’s location inputs can be sent in the default CF7 email along with other form data. View the location data directly on Google Maps.
  • Automatically get the user’s input data as a KML file in the email and view it easily using an online KML file viewer.
  • You can change map types, zoom level, and other map attributes according to your requirements. You can also center the user’s location.

Edit the rest of the settings such as markers, map types, and other attributes from the settings page, as shown below, and save the changes.

Maps and markers setttings

Create a Contact Form With a Map

Go to  Contact > Add New from your WordPress Dashboard menu. Contact Form 7 comes pre-configured with a ready-to-use template which looks like this:

The default Contact Form 7 template

To add a map field, click the Google Maps button and you should see a popup like this:

Google Maps popup

Click on Insert Tag, and the map appears as a field on your form. Your form should now look something like this:

The default contact form with a map


Go to the Mail tab and paste the [maps] shortcode in your email component to receive maps data in an email. Save all the changes. Each form, once created, generates a unique shortcode that you will use to embed it on a page.

Embed the Contact Form With Map Upload in a Page

The last step is to embed the form on a page or any other place you want it to appear. Go to Pages > Add New, give the page a title, and paste the shortcode on the body of the page as shown below.

The completed contact form shortcode

The complete form with a map will look like this:

The completed form with a map

As you can see, visitors can put markers on their location or use the search feature to search for their location. They can also draw shapes and zoom in and out just like on a normal map.


Knowing the locations of visitors filling out your WordPress forms can help you identify who is coming to your site and showing interest. Collecting location information can help you make better decisions about the type of services or products you offer. 


Biljana Jovanovic

Want to give your website a boost and transform its visual identity? Need a helping hand that will make your journey to the authentic website all fun and games? Start at Dribbble. Although there are many great online resources with free vector illustrations and free stock photos, you won’t get far if you are creating your website from scratch, with zero design knowledge. This is where Dribbble enters the scene. This famous platform is a way to go for everyone who wants to find and showcase creative work. In other words, Dribbble is a perfect place to share portfolio and get noticed by both designer experts and potential clients. If you’re looking for talented individuals or famous design studios that can help you with your new website’s look or any other design matter, Dribbble is the right starting point. From animation, illustration, print and product design, to typography and web design, this website features all the design types and elements you might need. If you are particularly interested in WordPress, we have a real treat for you: a curated list of top 8 WordPress designers on Dribbble! The order is random, so your perfect candidate may be at the bottom of our list. So, make sure you read everything from top to bottom.

Milica Andjelkovic

Milica is a designer of all shapes and forms, but her work is primarily focused on web design. Versatile and professional, her Dribbble work selection covers everything from the portfolio, and architecture, to travel, and yoga niche. What makes Milica’s design style characteristics is the mixture of great color combinations and amazing interactive animations. Have a look at Sekko for example. The perfect combination of pastel colors and progressive typography makes each homepage of this theme a little piece of art. Another relevant sample is Mixtape. Thanks to vibrant colors this eye-catching template particularly made for musicians is great for a lively presentation of any other kind.

Ishtiaq Khan Parag

As a product designer at Elegant Themes, this Bangladesh based visual guru, definitely knows how to stand out from the crowd. The facts he works for the creators of the most-widely used premium WordPress theme, says enough. With 7k followers on Dribbble and a portfolio that attract attention, Ishtiag is one of the designers you can’t ignore. Take Art Gallery template he created for Divi Theme as an example. This modern, elegant layout crafted in a minimal manner is almost a paradigm for everyone who wants that perfect balance of simplicity and bold details. In a similar style he also designed Elachii Landing Page. Gentle colors and tiny details are what make this template an absolute winner. As Ishtiag always goes one step ahead, his work is a proven inspiration resource for many design enthusiasts.

Stevan Ivic

This talented design professional from Qode Interactive demonstrated great attention to detail in his works. Specialized in graphic design, illustration and logo design, Stevan creates lovely illustrations nobody can ignore. Here you can check out Bolge, all-in-one portfolio theme with dominant navy, gentle pink and white colors. Meticulously crafted, this professional template is great for any creative niche – from marketing and SEO agencies, to creative design studios and branding companies. Also, we recommend you to check out Krafti, a stylish theme made for anyone who creates arts and crafts. Nice colors and gentle shapes of this theme will make you love Stevan’s work.


JayJay is another professional web designer with a great reputation on Dribbble. His flawless works are designed to perfectly fit your website. Besides websites, this talented artist also covers mobile apps, project management dashboards and much more. The versatility of his work and eye for detail are probably the reason behind his amazing list of clients. JayJay has collaborated with some of the leading global brands so it’s not surprising many designers follow him to get inspired. Ocolus sums up his style perfectly. Well-balanced elements and carefully chosen colors are the reasons JayJay is so well accepted at Dribbble.

Jelisaveta Stosic

Jelisaveta is another UX designer that made web designer her favorite playground. Her great graphic design skills and strong visual sense is visible in all the works she shared on Dribbble. Let’s take a closer look at Mintus, a bright, dazzling theme for creatives. As its name suggests, this theme brings a lot of mint elements and design details. Another example that shows Jelisaveta’s talents is Dor. Made for architects, this elegant theme is a great choice for everyone who prefers a simple, minimalistic design style. Dor also proves that less is definitely more.

Marina Pavlovic

Marina is UI/UX designers with over 5 years of experience in creating beautiful WordPress themes. Her contemporary, progressive style always seems to surprise with little, eye-catching details. Also, Marina is one of the contributors to Bridge, a Theme Forest creative bestseller. If you fancy a modern website look and feel, you should definitely check out other works of this designer. For instance, BoostUp – SEO Marketing Agency Theme, which is a great example of a sophisticated, yet vibrant business fashion. On the other hand, for all sweets lovers Marina crafted Panaderia, a delicious theme for every bakery and pastry shop. This beautifully designed theme has tons of lovely templates, all with balanced colors and trendy typography.

Beatris Veres

Based in Romania, but open to collaborating with clients worldwide, Beatris is a member of INK9 Creative Agency. Her rich colors and their amazing combinations, show all the power of this visual artist. Although you can see different aspects of Beatris’ work on Dribbble, this time we want to shed some light on the works she did for Bad Jokes and Dance Festival. If you like simple, yet effective forms and bright colors with dominant red, yellow, purple and white, the first example is for you. On the other side, Dance festival layout demonstrates a strong sense of mixing shapes, images and bold typography.

Mateusz Madura

Mateusz is specialized in creating websites, mobile applications and branding in general. His sophisticated style and talent for bringing different design forms under one aesthetic umbrella, never stops to surprise. Although Mateusz shares multiuse templates, ideal for different niches, each concept displayed on Dribbble is one, independent story. Every work example this designer shared is well-thought-out, authentic and ready to shine. However, our favorites are Seabedee and VidyArk – both made to help your WordPress site bloom.

Dribbble is a special place for the creative community with an endless amount of amazing design works. It’s also a perfect starting point for everyone looking for talented freelancers for part-time or full-time projects. We hope this list got you inspired or helped you find the right designer for hire. Follow us for more as we’ll keep on updating it with fresh authors.

We hope this article was helpful. If you liked it, feel free to check out some of these articles as well!


The WordPress websites can be vulnerable to bugging; resultantly, the data gets affected or gets completely crashed. The WordPress backup plugins, however, protect the data from getting affected. You certainly need to provide your WordPress website with the backup support for the recovery of the website if it gets trashed by the hacker or by any other factor. Due to the non-existence of backup support, you certainly have to recreate a website by consuming much effort and time.

Manual Backup Vs Plugin Backup

It is noteworthy here that providing the best WordPress backup plugin support to your website is very essential; however, it is at your disposal to opt for manual backup or plugin backup. To your information, the manual backup also works well; nevertheless, you need to be an expert in this regard. It is a technical task that does not afford even the slightest error. On the other hand, the plugin backup needs no expertise on your part; many plugins come with an automatic setting. It is worth mentioning here that all plugins are not the same. One can be different from others.

Some Important Instructions before Choosing Plugin

The first and foremost things are to decide whether you opt for a free plugin or paid plugin. Some of the plugins are free with limited features; to avail the advanced features, you have to pay for them. Having decided to use a plugin; you still need to know some basic things about a plugin; for example, it should be user-friendly; no detailed instructions should be there to confuse you while installing it. Moreover, the WordPress backup plugin should run automatically; you need not do the process manually after a week or two.

Provide the WordPress Backup Plugin Support

The plugin is required to provide full-site backup support; the WordPress backup plugin needs to support the complete website; not only to a text portion but also to the videos and other folders carrying important technical information.

Following are the Best WordPress Backup Plugins.

1. VaultPress


Automattic Inc. provides the service of it directly. Backpack has to be installed first to subscribe to the vault press. Once the service is activated your copies are saved at some off-site place; you continue to avail the plugin backup and security at the little amount of $3.75/month. You need not worry about your website and its security being backup by the highly functional tool.

2. Duplicator


While mentioning about the WordPress backup plugins, the experts surely discuss the duplicator as one of the best backup plugins. Due to worldwide popularity, the number of people is going beyond 100,0000, who have installed it across the world. The reason why this backup plugin has very popular around the globe is very simple; for example, it copies the entire website to provide you complete data you lose due to the crashing of the website. Nevertheless, it is worth mentioning here, that the person, who uses it, needs to be well trained about some technicalities of operating it. It is therefore suggested to hire a technical expert to run the plugin; instead of running it wrongly on your part. Once you hire a person to operate it or you take some training about operating it; the plugin better secures your website than the many other websites.

3. CYAN Backup


It is also a very effective WordPress backup plugin to secure your website. Moreover, it happens to be providing, hourly, daily, weekly, and monthly backup as per your need. In addition to it; you can opt for backing up limited data of your choice. It is at your disposal to use it as per your needs.

4. Backup Buddy


Another highly effective backup plugin secures your website as per your demand. You are free to avail of its services daily, weekly basis, or monthly basis. The paid plugin entertains your all needs quite effectively. Its services keep you free of mental stress by realizing you that the data of your website has gone in safe custody; it will surely be restored if the website crashes due to any reason. It is your true buddy like its name “Backup Buddy”

5. BlogVault Real-Time Backup


It has proved to be a very functional backup plugin keeping your website data off-site to recover easily at the time of need. The data can easily be restored once the website is crashed by a hacker or it crashes due to any other reason. The amount of money to get the service rests between $8 to $9 approximately. The biggest websites are also given backup plugin support by the “BlogVault Real-Time Backup”.

6. BackWPup – WordPress Backup Plugin


With more than 600000 installs, the plugin has been very popular around the globe; it creates an off-site back place to keep your data more secure than it is on your website. For your information, the plugin is available online free of charges; however, it provides customized services; if you need to avail it with full resources; purchase it online for the better security of your WordPress website.

7. WordPress Backup to Dropbox

Backup WordPress Site To Dropbox For Free

The backup plugin works with the Dropbox; what you need to do to have a dropbox account to keep your data secured. Commonly, it is free of charges plugin, however, the data exceeding the limit of 2 GB can’t be secured without paying for it. To use the plugin under discussion is as easy as using dropbox.

8. BackUpWordPress

backup WordPress

Due to having a huge capacity to make a copy of every available data on your website; the backup plugin has been very popular among the users. More than 1200000 downloads are proof of its workability. You just have to install it online after paying a little amount of money.

9. UpdraftPlus


The plugin is being used across the world by more than 2 million people. The plugin copies your web’s data at the off-site place and provides you at times you need it serve any purpose; for example, your website has crashed due to any reason.

10. BoldGrid Backup


The WordPress backup plugin is highly functional making too many copies of your website to restore your website when you need it. The plugin costs $60 annually; a very little amount as compared to the benefits you gain out of it.


The best WordPress backup plugins have made it possible to restore your website if it crashes; the backup plugins tool performs a great service.


Are you looking for the best WordPress giveaway plugins to run viral campaigns on your website?

Giveaway plugins for WordPress allow you to efficiently run a giveaway contest on your website. They allow you to maximize the incoming traffic and help you get tons of new visitors.

In this article, we will show you the best WordPress giveaway plugins to help you boost traffic, get subscribers, and improve your brand image.

Best giveaway contest plugins for WordPress

What to Look for in a WordPress Giveaway Plugin?

There are plenty of WordPress contest and giveaway plugins in the market, but not all of them have the specific features that you may need for creating a successful viral giveaway.

Some of them are good at helping you grow your email list while others are optimized to help you get more social media followers.

You need a WordPress giveaway plugin that combines the best of all features to help you increase your website traffic, grow your email list, and get more social media followers.

You also need to make sure that the plugin does not slow down your website.

Last but not least, you want to consider the costs and make sure that they are reasonable.

With that said, lets take a look at the best WordPress giveaway, contest, and sweepstakes plugin.

1. RafflePress


RafflePress is the best WordPress giveaway plugin on the market. It allows you to easily create highly effective viral contests and giveaways on your website.

It connects with all top email marketing platforms, so you can grow your email list.

You can also connect with popular social media platforms to get more followers and grow your website traffic from various social sharing actions.

RafflePress comes with a drag and drop giveaway builder which makes it easy to quickly build viral contests. It also has built-in templates to make the giveaway creation process even faster.

The refer-a-friend giveaway feature allows you to leverage word of mouth marketing by allowing users to share the giveaway on their social media profiles. This builds engagement and gets you tons of new visitors to your website.

RafflePress plugin also works with all WordPress form plugins, CRM Software, social networks, and lead generation software.

You also get tons of other powerful features like fraud protection, success tracking, retargeting, social logins, email verification, prize gallery, giveaway landing pages, and a whole lot more.

The giveaway works on mobile phones just as beautifully as laptops. You can also fully customize the giveaway appearance with your own images, colors, and fonts.

RafflePress has a free version available in directory, RafflePress lite, which you can try for free. To unlock the full power of RafflePress, you would need to purchase RafflePress Pro.

For more information, see our tutorial on how to run a giveaway / contest in WordPress with RafflePress.

Pricing: As mentioned above, RafflePress offers a free version that will help you get quick wins. However if you want all the powerful features, then the Growth plan costs $159 / year which is by far the best value compared to any other giveaway plugin in the market. For small business, their Plus plan ($39 / year) and Pro plan ($79 / year) are very well priced.

Note: WPBeginner users can get 20% discount on their purchase by using our RafflePress coupon code: WPBEGINNER20

2. Gleam


Gleam is a popular giveaway app that works with WordPress sites. It is available as a SaaS (Software as a Service) app for website owners to create giveaway and referral marketing campaigns.

There giveaway platform is extremely robust however the user interface for setting up a giveaway is not beginner friendly. There’s a setup wizard to connect your email email service, social profiles, and select actions for qualifying entries.

Once you have created the giveaway, you’ll be given a code snippet to paste in WordPress post or page where you want to add the contest.

Gleam also creates a separate giveaway landing page on their own website that you can use to promote the contest on social media.

All your contest data is stored on the Gleam website, and there are limited export options for user data. You will also need to upgrade to the Business plan to remove their branding and logo from your campaigns.

Pricing: The Business plan costs $149 per month which is what you need to unlock most of their powerful features. While they have lower level plans such as Hobby plan ($10 per month) and Pro plan ($49 per month), they are limited in features / integrations. Their free plan is extremely limited and is not even worth mentioning.

3. Rafflecopter


Rafflecopter is a popular giveaway / sweepstakes app for all kind of websites. It is available as a SaaS app, which means you’ll need to add the giveaway widget to your WordPress site using a code snippet.

It works with all major email marketing services and offers integrations with popular social media networks. Rafflecopter also comes with refer-a-friend feature, polls and survey options.

You can easily customize the appearance of the giveaway widget with your own images and background.

Rafflecopter has a limited free plan, and you’ll need to upgrade to one of their paid plans to truly make the most out of it.

Pricing: Basic plan costs ($13 per month) which gives you few additional features. If you want email integrations, then you will need to use their Grow plan ($43 per month). The ability to remove Rafflecopter branding and the powerful refer a friend feature is only available in their Premium plan ($84 per month).

4. Simple Giveaways

Simple Giveaways

Simple Giveaways is another good option to create a giveaway on your WordPress site. It is available as a limited free version, but you will need the paid plugin to access most features.

You can create your giveaway using their simple interface. The plugin allows you to add multiple ways to submit entries for the giveaway.

It has limited entry options and allows you to integrate Facebook, Twitter, few email marketing services, and other WordPress plugins. It also includes fraud protection with Match CAPTCHA and basic tracking reports for your contest.

Pricing: The premium version starts at $49 per year for 1 site.

5. KingSumo


KingSumo is a premium WordPress giveaway and referral marketing plugin. It comes with a simple user interface which allows you to easily create a viral giveaway.

It includes social sharing options for Facebook, Twitter, Facebook Messenger, and Instagram. It also works with several popular email services to grow your email list.

The plugin version of KingSumo is a bit outdated, and they have a new SaaS giveaway product that’s being promoted on the website.

Pricing: The SaaS giveaway app costs $228 / year. You can get the WordPress plugin version licensed at $198 for 1 site or $594 for unlimited sites.

6. WP Contest Creators

WP Contest Creator

WP Contest Creator is another good option to add giveaway contests to your WordPress site. It allows you to connect with popular email services, and you can create different social interactions for users to earn entries.

It also allows you to automatically send emails to users when they enter the giveaway. You can utilize these emails to tell users how they can increase their chances of winning.

Optionally, you can add gamification to your contest by displaying a leaderboard of participants with the highest entry scores.

It also provides some design options, but they are not as easy to follow as other solutions mentioned in the list. The plugin’s backend is also a bit complicated and beginners may find it a bit difficult to use.

Pricing: $69 / year for a single site license.

Which is The Best Giveaway Plugin for WordPress?

All the solutions we mentioned above allow you to run giveaway contests on your WordPress site. However, they each differ in terms of features, ease of use, speed, pricing, and privacy.

We believe RafflePress to be the overall best WordPress giveaway plugin for all users. It is extremely easy to use and comes with an intuitive drag and drop builder.

It runs on your own website, so you have full control of the data and user interactions. RafflePress also comes with success tracking and retargeting features which make your campaigns even more powerful. Their pricing is also by far the most affordable in the list.

If you don’t mind adding code to your WordPress site or run your giveaway on a SaaS platform, then Gleam and Rafflecopter can be a good option, but their premium versions are very pricey.

We hope this article helped you find the best giveaway plugin for your WordPress site. You may also want to see our guide on how to get more traffic to your website with practical tips.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.




WordPress calendar plugins come in many styles and have features to suit an equally wide variety of needs. Some calendars offer complex booking or scheduling features, while others are simple event management calendars. 

  • Whether you need an event calendar plugin, a booking system with payments, or a Google Calendar widget, this list of plugins will have something to improve…

  • In the digital age, users are online 24/7. Everyone prefers to check availability and make appointments, reservations, or bookings online. They want to do…

  • Build a schedule for your website, complete with Google Maps integration, call to action buttons, and a complete automated booking and ticketing system for…

  • Regardless of niche, adding a calendar plugin to your WordPress site is a great way to improve user engagement and retention. In this tutorial, I’ll show you…

Whatever your need, if you’re looking for a premium calendar plugin, this list of the ten best WordPress calendar plugins for 2019 will help you decide which one is right for you. 

1. EventOn


EventOn is one of the best-selling WordPress calendar plugins at CodeCanyon and it’s no wonder. The calendar’s default setting shows a small photo thumbnail with event name, date, time and location. When a viewer clicks on that info in the calendar, it opens up to display more details including an embedded Google map, social media share buttons, and buttons that allow you to add the event to Google calendar or your own calendar. Users can also add future events when they’re part of a series or recurring events, like for events that occur weekly or monthly. 

If you need even more customisation, there are a number of add-ons available that will allow users to add functions like events with a countdown timer, seating selections, and ability to review the event. There’s also a FullCal add-on that adds a clean, grid-based design to the calendar to display events in a traditional calendar format, and the appearance editor allows you to customise the look of the calendar to match your website style.

User alexsieff says:

“Very good program. I love the flexibility. You can buy the basic module, which works well, and gradually according to your needs, add add-ons. Good assistance.”

2. Bookly PRO

Bookly PRO

Bookly PRO offers users an automated online booking and scheduling calendar for WordPress. This fully-customisable booking form is responsive so that it can be used seamlessly on any device. It offers online payments, notifications, and syncs with Google Calendar. Booking lists can be searched, filtered, sorted and printed or exported to CSV.

Another great feature is the two-way synchronisation between Bookly Calendar and Google Calendar which automatically reflects all updates you make in either calendar.  

You can add more advanced functions to your default configuration with a wide selection of Bookly add-ons available with your purchase.

User Mabeny says:

“Great Plugin with several features and add-ons, really easy to customize and very quick, helpful and friendly support.”

3. Calendarize it! for WordPress

Calendarize it for WordPress

Whether you need a lightweight events calendar or one with more options and features, Calendarize it! is an excellent choice. That’s because, though it offers a traditional monthly events calendar as its default option, you can expand the functions of the calendar with the wide range of free and paid add-ons on offer.  

Some examples of great free add-ons available are the Social Share Panel, Member Profile, Ratings and Reviews, and the Visual CSS Editor add-ons. Other add-ons allow users to add a number of different calendar viewing options like an Event List View, Map View and Grid View.


“Brilliant Calendar plugin. They really bent over backwards to resolve an issue we were having. Top notch support, highly recommend to anyone looking for a calendar on their WordPress site”

4. Booked—Appointment Booking for WordPress

BookedAppointment Booking for WordPress

Booked—Appointment Booking for WordPress is a simple appointment booking calendar that allows you to create a number of calendars, each with their own time slots and custom feeds and then to assign each calendar to a specific user to manage. 

Some of the plugin’s outstanding features are guest booking which allows guest to book appointments without the need to register, custom time slots, custom appointment fields, customer ability to add events to their Google calendar, and colour customisation options.

User isntritchie says:

“Simple to use, yet complex to suit any need. A perfect combination. Support is fantastic and I cannot recommend this product high enough. I am a developer myself and everything from the interface to the performance is top tier!”

5. Timetable Responsive Schedule For WordPress

Timetable Responsive Schedule For WordPress

Timetable Responsive Schedule For WordPress is a powerful and easy-to-use WordPress event calendar plugin for users who want to create a timetable view of events in minutes and for users who want to take online reservations for an event within available free slots. These features make it an ideal plugin for solopreneurs like coaches and various kinds of teachers and tutors.

The plugin, which is also compatible with WPBakery Page Builder, comes with an integrated widget to display upcoming events in the form of a scrollable list. It is highly customisable and responsive and you can easily generate a PDF from your the timetable view if needed.

User zefstudio says:

“Great plugin! Easy to use! Modern design!”

6. WordPress Pro Event Calendar

Wordpress Pro Event Calendar

WordPress Pro Event Calendar offers an elegant and modern design, with responsive layout and easy to manage events. Some of its standout features are the ability to import events from ICS feeds and Facebook and to accept events submitted by front-end users, making it easy for users to add events. Other noteworthy features are Google Maps integration, custom fields and date range support, WPML support, ability to subscribe to a calendar, and much more. 

User datapress says:

“Great plugin and excellent support.”

7. Events Calendar Registration and Tickets

Events Calendar Registration and Tickets

Events Calendar Registration and Tickets is a great choice if you regularly run seminars, events, classes, workshops, conferences, concerts, etc. from your WordPress site and need to provide participants with a means to register or purchase tickets. 

The plugin allows you to not only manage your events, but also keep track of attendees, and sell tickets all from the admin section of your website. What’s more, the admin interface is easy to use and extensive documentation is provided to help you set up your events in no time. 

The all-in-one WordPress calendar plugin provides all the addons and features you need in an events calendar as part of the initial price, and you can rest assured that the software will be regularly updated to keep up with technological advances. 

User Han_Fei says:

“Great support, great plugin, really nice stuff… good job!”

8. Event Booking Pro

Event Booking Pro

If you’re looking for an event booking system, you need to check out Event Booking Pro. The responsive WordPress calendar plugin is loaded with useful features like offline booking, PayPal and coupon integration, support for unlimited events and more. 

There’s no shortage of shortcodes, and everything can be customised so that it integrates into your WordPress theme seamlessly. 

User Pahtreaq says:

“Great plugin that’s rather easy to work with”.

9. Events Schedule

 Events Schedule

Events Schedule is a simple WordPress calendar plugin that offers 12 unique schedule styles, each with different designs and features that can be modified with one click. Each style is suited to a different kind of business.

There are certain features that each template shares, like an elegant pop-up that provides more information about an event when you click designated areas of a calendar, the ability to assign certain details that make it easy to filter information in the calendars, and call-to-action buttons that you can insert to convince visitors to interact right away with your offer.  

User cjouper says:

“Has great template options for different ways to display calendars, depending on your content. When I needed help from tech support it was very quick and efficient. Highly recommend!”

10. HBook


HBook is a hotel booking system which is perfectly suited for anybody owning a business in the hospitality industry, be it a hotel, holiday apartment, or B&B. The booking system allows you to provide an online reservation system for your guests on your WordPress website. With it, you can add availability calendars, table rates and booking forms to your website quickly and easily. 

User emiliegrau says:

“Great customer support. Great plugin to take direct bookings from your own website. Nice integration with your own theme. You can also sync with major booking platforms.”

Choose the Best WordPress Event Calendar Plugin for You

Today we’ve looked at the ten best WordPress Event Calendars for 2019. Obviously, the one you choose will depend on your specific needs. Give one of these calendars a try and let us know what you think in the comments below. 

Meanwhile, if you’re interested in more options for calendar and booking plugins, check out the super helpful articles below. 


Are you looking for the best WordPress donation plugins?

Collecting online donations is a very effective way to raise funds for a non-profits, charities, relief funds, and special causes.

In this article, we will share the best WordPress donation and fundraising plugins that will help you easily collect one time donations as well as recurring donations using PayPal, Stripe, WooCommerce, other credit card processors, and even cryptocurrency.

Best WordPress donation plugins

How to Choose the Best WordPress Donation Plugin

There are dozens of WordPress donation plugins available in the market. The problem is that not all of them are easy to use, and a lot of them lack customization options.

Accepting donation payments on your WordPress website is an extremely important task.

You need a donation plugin that is reliable, works on mobile as well as desktop computers, supports your preferred payment gateway, sends receipts to donors, allow donors to make recurring donations, and is customizable enough to look good on your website.

On top of all that, you want a WordPress donation plugin that charges the least amount of fees. Ideally it should either be free or fixed yearly payment vs something that charges a percentage fee on all your donations.

We used the above criteria to compare the best WordPress donation plugins for non-profits and charities.

Here’s our editorial pick for the top WordPress donation and fundraising plugins.

1. GiveWP


GiveWP is one of the best WordPress plugins for non-profits to accept donations and raise funds for your cause.

What makes GiveWP standout and earn the top-ranked spot in our best WordPress donation plugin list is their complete set of features along with their non-profit friendly pricing model.

GiveWP makes it easy to create a custom donation form inside WordPress to easily setup one-time donations as well as recurring donation options.

You can integrate with a wide variety of payment gateways to accept credits card donation payments including Stripe,, PayPal, 2Checkout, Braintree, Mollie, Paytm, PayFast, Square, AmeriCloud, Paymill, and many more.

GiveWP also allows you to fine-tune just about every aspect of your donation process with features like customizable donation tributes like “in honor of”, multi-level donations, campaign level donation goals / incentives, currency switcher options, tax deductible donation receipts, and more.

It comes with a complete donor management area with full-featured reporting, so you can easily manage all your donations (both online and offline donations).

GiveWP integrates with all major email marketing services, so you can easily communicate with your donors about seasonal gift giving campaigns.

If you run an online store with WooCommerce, then GiveWP allows you to add a donation upsell on the checkout screen, and they have seamless Google Analytics integration with enhanced eCommerce tracking.

GiveWP’s offers a free WordPress donation plugin, but you will have to upgrade to their yearly paid plans to unlock all the powerful addons and features. Basic paid plan starts at $240 / year, but you will need the Plus plan ($360 / yr) to get all their add-ons.

2. WPForms


WPForms is the most beginner friendly drag & drop form builder for WordPress. It comes with a built-in form template to create an online donation form on your website.

A lot of smaller charities and non-profits don’t need a full-featured giveaway platform. Instead they just want a simple and easy to customize donation form that can accept one-time and recurring donations.

WPForms offer you just that. It integrates with both PayPal and Stripe, so you can securely collect donations via credit card right on your website.

Since WPForms is a more comprehensive form builder, it can also serve multiple purposes for a charity website such as contact form, survey forms, polls, email newsletter signup form, volunteer signup form, etc.

WPForms seamlessly integrates with all major email marketing services and CRM platforms like Constant Contact, SendinBlue, AWeber, MailChimp, and hundred others.

WPForms free plugin is used by over 2 million websites, but you will need their payment addons to accept online donations. They offer a special discounted license for non-profits at only $99 / year which is 75% off their regular price.

This gives you all of their Pro features that lets you build donation forms as well as other types of forms that we mentioned above. You can see the full list of over 150 form template demos here.

Note: WPForms is a sister company of WPBeginner. The plugin was co-created by WPBeginner’s founder, Syed Balkhi.

3. Easy PayPal Donation

PayPal Donation for WordPress

Easy PayPal Donation is a free WordPress donation plugin that lets you add a PayPal donate button on your website.

Your website visitors can click on the button and send donations using their PayPal account or credit card.

This is a very simple donation plugin that comes with 7 button templates, and you also have the option to upload a custom button style to match your design.

The goal of this plugin is to make it easy to connect your PayPal account with WordPress and receive the donations. This plugin also allows visitors to choose recurring monthly donation options.

We have this plugin listed as #3 not because it’s the most feature-rich, but because sometimes you may not need all the features that plugins GiveWP and WPForms offer.

If you don’t want to customize your donation form and want a straight-forward solution that’s completely free for accepting one-time donations, then this plugin can do the job for you.

For setting up recurring donations, you will need their Pro version which costs $59.95 / year at which point you’re better off going with WPForms because you get a lot more value.

4. WP Crowdfunding

WP Crowdfunding by Themeum

WP Crowdfunding is a powerful WordPress fundraising plugin that helps you create a fundraising backer site like GoFundMe or KickStarter.

You can use the crowdfunding campaign style only for your charities or even offer an aggregate fundraising platform for other charities in your network.

It integrates with Stripe, PayPal,, and all WooCommerce gateways if you choose to process your payments with WooCommerce. WP Crowdfunding Native wallet system allows you to track pledges for each campaign and distribute funds accordingly to individual stakeholders.

If you’re looking to create an aggregate crowdfunding site like GoFundMe, then you also have the option to charge a commission fee for helping other charities collect donations.

The base plugin is free, but you will need to upgrade to the paid plan to unlock full features which starts at $149 / year.

5. Charitable


Charitable is an easy WordPress donation plugin that allows you to create unlimited fundraising campaigns and set goals for your cause.

You can select a fixed donation amount, add a custom amount, or both. You can embed the donation form on your pages, posts, sidebars, and modal popups.

While the base plugin is free, you do have to upgrade to their Plus plan ($99 / year) to unlock their payment gateways like Stripe,, etc as well as newsletter sign up forms.

If you want recurring donations, crowdfunding, peer to peer fundraising, donor fee relief, and other powerful features, then you will need their Pro plan which costs $249 / year.

6. Seamless Donations

Seamless Donations

Seamless Donations is a free donations plugin for WordPress. It gives you complete control to collect and manage donations within the WordPress dashboard.

Seamless Donation works with PayPal, so users can make donations using their PayPal account or credit cards.

You can accept one-time donations or recurring donation payments. You can also allow users to select which campaign they want their funds allocated.

Unlike other plugins, Seamless donation sells few addons on an a-la carte basis such as Thank You Enhanced which lets you setup custom thank you pages and Giving Level Manager which lets you attribute custom donation levels.

7. Donorbox


Donorbox is a powerful donation form plugin that works on both WordPress as well as standalone websites.

It allows you to setup one time donations as well as monthly, annual, and weekly recurring donations. You have the option to do company gift matching and accept company donations.

Donorbox allows you to accept payments from credit cards as well as popular payment platforms like Apple Pay, Google Pay, PayPal Express with One-Touch, and ACH bank payments for US and Europe based donors.

It also comes with many other powerful features like Goal Meter, Donation popup forms, multi-currency support, donor wall, donor profile, complete donor management, end of year tax receipts, and so much more.

The reason why we have Donorbox listed towards the bottom in our list is because their pricing is not friendly to non-profits.

While they let you collect free donations for up to $1,000 per month, you will have to pay a 1.5% platform fee for all other amounts. This platform processing fee is in addition to the payment processing fees that are added by Stripe, PayPal, and other banks.

They do have the option to have your donors cover the fees, but we believe its better to use a platform like GiveWP where more of the donation money goes towards the actual cause.

Donorbox also charges separate monthly fees for various email marketing and CRM integrations.

To be fair, out of other SaaS donation platforms like Crowdrise, Donately, etc, Donorbox is by far the most affordable.

The reason why you may want to use the Donorbox platform is because they take away the technical management headache away from you.

You don’t have to worry about the security of your payment infrastructure because it’s all handled by their team.

8. Formidable Forms

Formidable Forms

Formidable Forms is the most advanced WordPress forms plugin. It allows you to easily create complex forms with drag and drop builder.

It has tons of form templates including a pre-built template to collect online donations. You can view the donation stats in graphical charts within the WordPress dashboard.

The plugin allows you to export the form data outside WordPress. It also gives you the option to import your donation entries from third-party services. Formidable Forms is fully compatible with the WPML translation plugin to translate the form in any language.

9. Donation Thermometer

Donation Thermometer

Donation Thermometer is a classic WordPress donation plugin. It uses a thermometer style parameter to display the collected funds and your target amount.

It is ideal for sharing your fundraising campaign with your website visitors and motivate them to help out. It is also perfect for organizers to see how close or far away they are from their fundraising target

The thermometer is fully customizable for colors, text, currency, meter size, and more. You can use a shortcode to display the donation thermometer in your posts and pages. All settings are easy and manageable within WordPress.

It’s important to note that this plugin DOES NOT help you accept any donations. You can use it alongside any of the other WordPress donation plugins in this article.

10. PayPal Donations

PayPal Donations

PayPal Donations is another free WordPress PayPal donation plugin to raise funds for charities and non-profits. You can use their sidebar widget or the shortcode to add the PayPal donation button on your website.

Like other PayPal plugins, it lets you connect WordPress to your PayPal account and accept donations from visitors. Other settings include multiple currencies, localization, multiple button sizes, and more.

11. YITH Donations for WooCommerce

YITH Donations for WooCommerce

YITH Donations for WooCommerce allows you to add an option to collect donation in your online stores.

You can run seasonable campaigns to support your causes. Each time a user adds a product to cart, they will be prompted with an option to make a small donation.

This concept is utilized by many in the retail world, and YITH Donations for WooCommerce allows you to add this to your eCommerce website.

YITH has a free version of the plugin that’s quite limited. To get all the features like donation form on cart page, customize amounts, donation receipts, etc, you will need the premium version of the plugin which costs $59.99 for a single site.

Note: GiveWP also offers this feature along with a lot more which we believe is a better value.

12. Cryptocurrency Donation Box

Cryptocurrency Donation Box – Bitcoin & Crypto Donations

If you’re looking to accept donations in cryptocurrency, then look no further. This free WordPress donation plugin allows you to accept donations in top 20 major cryptocurrencies.

You can accept payments in Bitcoin, Ethereum, Bitcoin Cash, Litecoin, Cardano and more.

Which is the Best WordPress Donation Plugin?

The plugins we mentioned in this article can all help you collect donations on your WordPress. However deciding the best WordPress donation plugin for your online fundraising will vary based on your needs.

If you’re looking to create a simple donation form with one-time and recurring donation option along with the ability for users to make payments via PayPal or credit card, then WPForms non-profit plan is the best value because they’re offering 75% off discount.

If you want a WordPress donation plugin that comes with advanced features like complete donor management, tax deductible donation receipts, campaign level goals / incentives, multi-level donations, customizable donation tributes like “in honor or”, full-featured reporting, a wide-variety of payment platform integrations, then nothing in the market beats GiveWP, and that’s why GiveWP is our pick for the #1 best WordPress donation plugin.

We hope this article helped you find the best WordPress donation and fundraising plugins for charities and non-profits. You may also want to check out our expert pick of the best WordPress page builders and must have WordPress plugins for all sites..

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.


WordPress Donation Plugins

Reading Time: 9 minutes

Nonprofit organizations help make this world a better place to live. They play a vital role in helping the society engineer a positive change amongst the masses. In order to spread awareness about their cause, many nonprofit organizations have to rely on their website – as a sole source of collecting funds – in today’s digital landscape. Although many nonprofit organizations operate on a limited budget, that shouldn’t stop them from running a powerful website.

A scalable Content Management System (CMS) like WordPress can help you spread awareness about your cause and WordPress donation plugins can help you raise funds with ease. It doesn’t matter whether you volunteer, work with a philanthropist, or are bootstrapping on your own, this article will help you to identify the best WordPress donation plugins for your nonprofit organization so that you can generate funds with minimum effort.

The Science behind a successful Nonprofit Website:

In simple terms, the science behind any nonprofit website revolves around two components. One is an effective CMS and the other one is a reliable web hosting solution.

Let’s delve deeper!

You cannot undermine the power of a well-built website, and WordPress is an excellent choice for nonprofit organizations, regardless of their size. At some point or the other, your volunteers, partners, donors and every person who shows interest in your cause will visit your website for additional information, henceforth, you must prepare yourself.

Why Nonprofit Organizations should use WordPress?

Amongst the obvious, the following are the primary reasons why nonprofit organizations must consider WordPress to build an engaging website and highlight their cause.

    • It’s free to download and customize
    • It’s easy to learn and use, compared to other CMSs
    • A wide range of WordPress themes for nonprofit organizations is available
    • Various WordPress plugins for nonprofit organizations allow them to add powerful features on their website
  • A huge online community of WordPress experts is available to help you support, document, and code so that you can come up with the best website possible.

Web Hosting for Nonprofit Organizations

Shared hosting or dedicated hosting is not viable for nonprofit organizations as they are heavy on the budget and can’t sustain the sudden traffic spikes. Henceforth, cloud hosting is the ideal solution that can allow nonprofit organizations to scale their website.

Cloud hosting is pocket-friendly, scalable, and optimized for fast performance. One of the top cloud hosting providers available today include DigitalOcean, Amazon Web Services, and Google Cloud Engine. Cloud hosting can be technical for some, however, you can always opt for a managed cloud hosting platform like Cloudways that offers managed WordPress hosting solutions.

Payment Gateways

A payment gateway technically is a fraud prevention technique practiced by international payment processors. They protect your donors’ credit or debit card information during and after the donation process which goes like this:

  • Step 1: Donor makes a contribution
  • Step 2: Information goes into the payment gateway
  • Step 3: Donation transferred into the payment processor’s account
  • Step 4: Donor information goes into a database
  • Step 5: Money is deposited in the nonprofit’s account

To list a few, some top payment processors for nonprofit organizations available today are iATS Payments, BluePay and ClearView CRM.

WordPress Donation Plugins for Nonprofit Organizations

WordPress plugins can enhance the functionality of your website which the basic themes are unable to do so. Considering different aspects such as quickly indexing on SERPs or fundraising, the arsenal of WordPress plugins can provide you more control of your website. However, my goal here is to provide you with a list of the best WordPress Donation Plugins for Nonprofit Organizations. Thence, without further ado, consider the following donation plugins as one amongst the best available today.

1. Give

Give WordPress Donation Plugin

Plugin Specifications

Active installations: 60,000

WordPress Version: 4.8 or higher

Rating: 5 stars

Give WordPress plugin is one of the most downloaded WordPress donation plugins. You can install Give and purchase additional add-ons to extend the functionality of your website.

Overall, this plugin provides an ample amount of functionalities so that you can customize your fundraising platform as per your requirements. It lets you easily integrate various third-party payment gateways and services like Stripe, PayPal, and You can also keep a track of your donations via Google Analytics.

Furthermore, it lets you receive donations with the assistance of customizable donation forms. It also generates tax deducted receipts for your donors. With a complete donor management system, you can analyze various reports that deliver a complete summary of the donation activities. You can also add goals, your terms, and conditions, alongside the option to donate multiple amounts.


Basic: $20 per month (billed annually)

Plus: $30 per month (billed annually)

Pro: $40 per month (billed annually)

2. Charitable

Charitable WordPress Donation Plugin

Plugin Specifications

Active installations: 10,000

WordPress Version: 4.1 or higher

Rating: 5 stars

Charitable donation plugin is both developer-friendly as well as user-friendly. Its users can work with a comprehensive interface and get their fundraising campaign up and running within minutes. Great thing is that it’s compatible with almost every standard WordPress theme.

With more than 10,000 active installs, Charitable boasts a 5-star rating from its users.  Unlike other top donation plugins for WordPress, it doesn’t charge its users a fee on every donation/transaction.


Starter: Pay What You Want (Min $19)

Plus: $99 per year

Pro: $249 per year

3. PayPal Donations

PayPal WordPress Donation Plugin

Plugin Specifications

Active installations: 50,000

WordPress Version: 3.0 or higher

Rating: 5 stars

PayPal Donations plugin is a popular donation plugin in the WordPress directory. As the name suggests, this trending WordPress donation plugin can accept payments or donations via Paypal – the most trusted global money transfer service.

This free WordPress plugin lets you add a donation button on any web page, post or sidebar by using a simple pre-generated shortcode or widget. Also, the option of changing different settings, comprising currency, custom payment page style, and the return page truly sets it apart from the rest.



4. Seamless Donations

Seamless Donation WordPress Plugin

Plugin Specifications

Active installations: 10,000

WordPress Version: 3.4 or higher

Rating: 4 stars

This great WordPress donation plugin is free and offers an extremely quick set up process. Your non-profit business website will be ready to accept donations within five minutes after installing this plugin.

Seamless Donations offers its services in more than 20 currencies. Your donors can choose whether to make a one-time donation or a recurring donation, depending on your cause. Also, it lets you send custom thank you emails once the donation has been made. Moreover, it’s premium add-ons can extend your website’s functionality and help you make the most out of your fundraising campaigns.



5. Woo Donations

Woo Donation Plugin

Plugin Specifications

Active installations: 1,000

WordPress Version: 3.0.1 or higher

Rating: 5 stars

If you’re running an online store on WooCommerce, you can make Woo Donations a part of your nonprofit website and accept donations through your ecommerce store.

The core functionality of this WordPress plugin is that it adds the donation as a regular product. Your customers can add the donation/product to their shopping cart, and pay for it without any actual product in return unless you choose to offer giveaways against a donation for your cause.

When the customer actually purchases a tangible product from your online store and also donates to your cause in the same transaction, Woo Donations adds everything to the customer’s total amount. It creates and delivers reports on the backend, which also informs you how many donations you have collected, and how much revenue is coming in from regular sales.



6. Smart Donations

Smart Donation WordPress Plugin

Plugin Specifications

Active installations: 3,000

WordPress Version: 3.1 or higher

Rating: 4 stars

This unique WordPress donation plugin proudly promotes itself as an ‘all-in-one donation plugin’. Smart Donations lets you create customizable donation forms for various nonprofit causes, analyze the results of the fundraising campaign, and later on send thank you emails to generous donors.

As soon as you install it, you can create different donation campaigns, set various goals, create custom donation forms, as well as automate thank you emails. Regardless, talking about compatible payment gateways, Smart Donations only accepts PayPal and Stripe for the time being.


Personal: $19.99

Pro: $29.99

Unlimited: $49.99

7. Donorbox

Donorbox WordPress Donation Plugin

Plugin Specifications

Active installations: 5,000

WordPress Version: 3.0 or higher

Rating: 5 stars

It is another freemium WordPress donation plugin that only charges a 1.5% platform fee when you receive a donation of over $1000 per month. Donorbox will allow you to seamlessly embed a custom donation form on your nonprofit website where you can customize each and every field.

You can deploy Donorbox form(s) in 15 minutes, and brand your donation page with your own brand’s color scheme, styling or logo. You can customize input fields in order to make your donation forms more comprehensive and quick to complete. You can set amounts for donors to choose from whereas they can specify their own amount of donation as well.

Donorbox accepts a range of currencies via Stripe, PayPal, Apple Pay and Google Pay. With a quick and easy checkout process, you can double your donations with its seamless employer donation matching feature. Their forms are localized in various languages like English, Spanish, French, German, Italian, and Portuguese.



8. Cryptocurrency Donation Box

Cryptocurrency Donation Plugin

Plugin Specifications

Active installations: 700

WordPress Version: 4.5 or higher

Rating: 4.5 stars

With cryptocurrencies taking the world wide web by storm, you might consider adding Cryptocurrency Donation Box to your nonprofit website. Despite you’re generating funds for a noble cause, or just wish to keep your website alive, this suitable WordPress donation plugin offers an innovative approach to attract donors who are willing to donate via crypto coins.

This donation plugin exclusively accepts over twenty different cryptocurrencies such as Bitcoin, Ethereum, Litecoin and many more. With its beautiful crypto donation box design and mobile-friendly responsiveness, you can generate donations in the form of crypto coins with ease.



9. YITH Donations for WooCommerce

YITH Donations for WooCommerce

Plugin Specifications

Active installations: 800

WordPress Version: 3.5.1 or higher

Rating: 4 stars

One of the best WooCommerce donation plugins is YITH Donations. You can use it in your online stores to generate more revenue or raise funds for a nonprofit cause. As soon as you install and activate this donation plugin, you can start raising donations immediately.

You can associate the donation form to a single product or multiple products by ensuring you name each donation project differently. Additionally, this plugin comes with a donation widget which you can easily attach on to your sidebars or footer section.


Single Site: € 49.99 ($55 approx)

Six Sites: € 99.99 ($110 approx)

Thirty Sites: € 169.99 ($188 approx)

10. Direct Stripe

Direct Stripe WordPress Donation Plugin

Plugin Specifications

Active installations: 3,000

WordPress Version: 4.7 or higher

Rating: 4.5 stars

Stripe itself is a popular payment gateway. If your nonprofit organization is seeking donations for a cause with just one payment provider i.e. Stripe, then this is the perfect WordPress donation plugin for you.

Direct Stripe allows you to receive Stripe payments, subscriptions, and more importantly donations, on your WordPress website without hassle. It enables you to add high-converting Stripe donation forms and buttons to your nonprofit website.

You can easily customize the buttons and forms, and add them to your website using a shortcode. Moreover, you can also automate emails and send them to your donors each time they make a contribution.



11. Donation Content Locker

Donation Content Locker Charity Plugin

Plugin Specifications

Active installations: N/A

WordPress Version: 3.0 or higher

Rating: 5 stars

This savvy donation plugin for WordPress lets you restrict content and display it to only those who contribute to your cause with a donation.

With pre-generated shortcodes, it wraps protected content and asks your website visitors for a minimum donation (set by you) to access the content. Once the donation is made, the donor receives an activation link that allows them to unlock all the protected content.

Donation Content Locker is a user-friendly WordPress plugin that allows you to monetize your nonprofit website with ease and ultimately increase donations.


Regular License: $16

Extended License: $80

By and large,

There you have it! The list of 10 best WordPress donation plugins that are currently on a roll among nonprofit organizations. These donation plugins aim to make the lives easier of nonprofit organizations so that they can raise funds for charity, or any other noble cause in order to make this world a better place. If you’re using any other donation plugin that is not mentioned in this list, please let us know in the comments section below.

Share your opinion in the comment section.

Start Growing with Cloudways Today!

We never compromise on performance, security, and support.

Reza Merchant

Reza Merchant is a Foodie by passion and a Digital Marketer by profession. He enjoys creating digital content for various platforms and aspires to be the change he wants to see in this world.