WORDPRESS
7 Best Crowdfunding Plugins for WordPress (Expert Pick for 2024)
At WPBeginner, we’ve helped many nonprofit and small business projects get off the ground, and we’ve seen how the right crowdfunding tools can make all the difference.
Sifting through the many crowdfunding plugins for WordPress can be a headache, and let’s face it: not all plugins are up to par. The right tool allows you to easily launch and scale your campaigns with minimal difficulty or fees.
That’s why we’ve done the research and put together a list of the best WordPress crowdfunding plugins so that you can find the right fit for your next venture.
What Is a Crowdfunding Plugin, and Why Do You Need One?
Fundraising can be a challenge, especially for entrepreneurs and small businesses. You might have the perfect business plan and website, but that doesn’t matter if you don’t have the funds to start it.
That’s where crowdfunding comes in. It involves raising awareness about a new business venture that you are considering developing and getting small contributions from people.
Rather than go to sites like Kickstarter and IndieGoGo, which take a cut of your funds and restrict your ability to add customizations, a crowdfunding plugin gives you full control.
There are many advantages to crowdfunding in WordPress, such as:
- Access to capital: Crowdfunding allows you to get access to capital when it may not be feasible or easy to secure funding from traditional sources like banks or other lenders.
- Market validation: By presenting your idea to the public, you can gauge the interest and see if your product is something that people would actually pay for. For example, you can accept donations and include a survey form so that your team can collect valuable feedback from contributors.
- Audience building: Crowdfunding allows you to reach a large number of people so you can generate awareness and build an audience. Those who contribute to your campaign will likely be loyal customers and advocates. It’s a good idea to use a plugin like MemberPress so you can give contributors a place to share their thoughts and ideas in a private forum.
- Customization: You have control over your enter campaign design and branding. You can even combine other plugins to help boost your crowdfunding efforts. For example, you could use other plugins like RafflePress to incentivize others to share your campaign to increase awareness.
- Data ownership: When you choose WordPress, you own the data. You can build your email list with plugins like OptinMonster, which allows you to send updates to your subscribers about your new business venture.
With all said, let’s dive into the best tools building for starting your crowdfunding campaigns.
1. Charitable
Out of all the options we tried, Charitable is the best crowdfunding plugin for WordPress. It allows you to create peer-to-peer fundraising campaigns without using a separate hosted fundraising platform, and it doesn’t charge transaction fees.
It allows you to easily build attractive fundraising pages and forms on your website. Plus, it lets you set up peer-to-peer fundraising and build brand awareness much faster, which ultimately can get you more funding for your business venture.
Charitable offers a wide range of add-ons, making it possible to handle just about any use case. For example, you can find addons like Donor Comments to add testimonials. You can also add a video introducing what your new business project is all about. It’s a great way to get people excited about the idea and increase conversions.
Here’s an example of a video, description, and donation button added to the crowdfunding form on Charitable.
Charitable comes with other cool extensions like PDF receipts, so contributors can keep their invoices for tax write-offs. Plus, you’re able to connect the plugin to email marketing services so that you can send subscribers updates about your venture, which keeps them informed and excited about what’s going on.
Pricing: Charitable starts at $69 per year. There’s also a free version of the plugin.
Pros:
- Lots of add-ons to increase functionality
- Plenty of payment methods
- Easy to use crowdfunding form editor
Cons:
- You will need to pay for the premium versions to get access to the add-ons.
Why We Recommend Charitable: Charitable is the best way to raise money with crowdfunding in WordPress. Since you can set up peer-to-peer fundraising, it allows businesses to leverage their networks to reach more people.
2. WP Simple Pay
WP Simple Pay is the best Stripe payments plugin for WordPress. It allows you to easily accept donations and other types of fundraising payments on your site. One of the best things about this plugin is that you won’t need to set up an online store or even a checkout page.
You can build a crowdfunding form and embed it anywhere on your site. Plus, with its advanced form builder, you can customize it however you like. There are plenty of text fields, dropdowns, and price options to add.
The flexible donation and fundraising forms offer cool features to help drive more conversions. For example, you can create a predefined suggested donation amount to increase the average donation.
We particularly appreciated how WP Simple Pays offers recurring donations because this allows you to create a steady stream of funding for your organization. Best of all, the plugin accepts 13+ payment methods, so you can appeal to a wide range of donors from around the world.
Pricing: WP Simple Pay starts at $49.50 per year, but there is a free version available as well.
Pros:
- Accepts 13+ payment methods and multiple currencies.
- You can provide customizable receipts that help contributors for tax purposes.
- The advanced form builder is easy to use.
Cons:
- It doesn’t offer any community-building features.
Why We Recommend WP Simple Pay: We like WP Simple Pay as a quick and easy solution for accepting donations. You can choose to create payment forms or an entire donation page, and the payment process is seamless.
3. GiveWP
GiveWP is another donation plugin for WordPress with a variety of crowdfunding features. Like many of the other plugins on our list, it comes with an easy-to-use form builder so that you can easily customize the donation form without any code.
One of the best aspects of GiveWP is its mobile donation capabilities. Mobile-friendliness is integral for any business, let alone a new venture you’re starting.
The easier you can make it for contributors to donate, the better. GiveWP offers easy-to-pay options like Venmo Donations, Apple Pay, Google Pay, and even Text-to-Give. That means, with a simple text message, donors can easily contribute to your new venture anytime from anywhere.
Inside the plugin dashboard, you’ll receive real-time crowdfunding reports, so you can view metrics like top donors, average donation amounts, and more. This allows you to optimize campaigns and tweak your form or page for better conversions.
Pricing: GiveWP is free to start, but the basic plan starts at $149 per year.
Pros:
- GiveWP offers a few mobile-pay options.
- It provides in-depth reporting.
- Easy-to-use plugin.
Cons:
- The plan is pricey once you upgrade to the paid version.
Why We Recommend GiveWP: GiveWP is a comprehensive tool that gives you all the essentials for crowdfunding. It’s great if you want to prioritize mobile donations since users can easily pay through texting or popular apps like Venmo.
4. WPForms
WPForms is a contact form plugin for WordPress that can accept crowdfunding payments and other transactions. With crowdfunding forms, you can accept donations through a wide range of payment gateways, such as PayPal, Stripe, Square, Authorize.net, and others.
Chances are, if you’re building a new product or business, you’ll need other form types as well. That’s where WPForms excels. You can create forms for all sorts of purposes, like contact forms, newsletter signups, surveys, registration forms, and more. It’s an all-in-one form builder with over 1700+ templates to choose from, which is more than any other plugin on this list.
Out of all the plugins we tried, WPForms is the best for collecting user responses in your crowdfunding forms. That’s because advanced features like the smart logic condition allow you to collect relevant information based on the contributors’ responses.
For example, depending on the contribution level, you may consider adding a reward.
Let’s say VIP contributors will get access to a special launch event. In that case, you’d need to collect information about them so they can RSVP. Or if you’re sending physical rewards like gifts or merchandise, then the smart logic would prompt users to provide their shipping address for delivery purposes.
WPForms comes with a wide range of add-ons like email marketing so you can send donors updates. There are plenty of integrations with third-party apps to enhance functionality. For instance, adding integration with CRM apps allows you to follow up with contributors once your business launches.
Pricing: You can get started with WPForms for $49.50 per year, but there’s also a Lite version.
Pros:
- WPForms comes with 1,700+ templates.
- Smart logic is a great option for showing or hiding fields based on responses.
- There are plenty of third-party integrations to increase functionality.
Cons:
- It’s not a dedicated crowdfunding platform.
Why We Recommend WPForms: We like WPForms because of its wide range of templates and customizations. Beyond that, smart logic is an excellent way to show only relevant fields, which is great if you offer reward-based crowdfunding.
5. WP Crowdfunding by Themeum
WP Crowdfunding is a crowdfunding plugin that leverages the power of WooCommerce to accept and manage pledges from backers.
It’s great because it integrates with all of your other products and categories.
For example, let’s say you have a dropshipping store but want to build your own branded products and start private labeling them. Rather than investing time and resources into products your customers aren’t interested in, you can raise money to help support items that people are willing to pay for.
You can even add all of your crowdfunding campaigns in one place, similar to Kickstarter or Indiegogo. That way, visitors can see which product to support.
The plugin also has its own Native Wallet system, which tracks all of the proceeds that are raised on the crowdfunding project. That way, you don’t mix up online sales with donations. You’ll get stats along with a list of backers, so you know all the contributions made.
Pricing: WP Crowdfunding costs $149 per year for a single site.
Pros:
- WP Crowdfunding connects with your WooCommerce store.
- It helps you decide which products to launch.
- Backers can donate visibly or anonymously.
Cons:
Why We Recommend WP Crowdfunding: This plugin is a great choice for online stores that want to start selling their products. Visitors can see all of the crowdfunding campaigns available to contribute to and see the progress towards each goal.
6. Formidable Forms
Formidable Forms is another form builder plugin, like WPForms. It comes with a wide range of donation forms, payment forms, calculator forms, contact forms, and more.
With this plugin, you can easily create donation and fundraising forms that accept payments via Stripe or Authorize.net. When using Formidable Forms, you’re taken to a visual form styler, giving you plenty of customization options. You can add a donate button, custom amounts, and just about any field you’d like.
While it is a contact form plugin, you can still view donation stats based on all the contributions made. There are beautiful graphic charts that help you visualize your campaign’s performance.
It also has integrations with powerful apps like Zapier, so you can automate workflow tasks. For example, you can set it up so that all contributors receive a thank-you message via email or text.
Overall, we found that Formidable Forms had lots of built-in customization choices. After thorough testing, we do like that it has advanced calculation features. For example, for large donations, you might include a calculator to estimate the tax-deductible portion of the donation.
Pricing: Formidable Forms starts at $39.50 per year but also offers a free version.
Pros:
- Lots of form templates.
- A visual form styler to customize the fundraising form to fit your brand identity.
- Visual reporting to easily see campaign performance.
Cons:
- It’s not specifically designed for crowdfunding purposes.
Why We Recommend Formidable Forms: This plugin could be a good choice if you need a customizable tool for collecting donations. It supports all the popular payment gateways, and you can add advanced features like calculators to your donation forms.
7. Patreon WordPress
Patreon WordPress is a fundraising plugin that allows you to connect your WordPress site to your Patreon account to boost your pledges and patrons.
Let’s say you already have a built-in audience on Patreon but want your visitors to also have access to your community. Then, you can easily import your existing Patreon posts and content.
The plugin will sync data automatically to WordPress. When donors pledge and subscribe to your Patreon, they can easily access everything from your website.
You might have a new business idea. All contributors can be added to your Patreon community, giving them exclusive access to your gated content. You can choose to restrict any single post or all of your posts. In addition, you can select the tiers or minimum pledge amount needed to access any custom post or type of post.
Pricing: Patreon WordPress is a free plugin.
Pros:
- Good for creators and existing Patreon users.
- It syncs from Patreon to WordPress.
- You can choose to lock or unlock any single post or all posts.
Cons:
- It’s not useful for anyone who doesn’t plan on using Patreon.
Why We Recommend Patreon WordPress: This is the perfect plugin for creators, artists, musicians, bloggers, and other creatives who are already on Patreon. You’ll be able to bring the power of Patreon onto your website and integrate the platforms.
How Do You Choose the Best Crowdfunding Plugin?
The right crowdfunding plugin will depend on your needs. Some plugins are specifically designed for crowdfunding, while others offer fundraising forms as part of their larger offering.
If you offer other products or services or want to set up different types of forms on your website in addition to the fundraising form, then using an all-in-one plugin could be the more cost-effective solution for you.
Beyond that, it’s vital that you provide donors with a fast and easy checkout experience. That means you should offer a wide range of payment gateways so contributors can pay using their payment method of choice.
If you’re only planning to build a few pages to gauge interest level with any of these plugins, you may want to use SeedProd. It is the best page builder plugin on the market, with a powerful drag-and-drop editor that allows you to easily create any type of page, like a landing page or a custom homepage.
That way, you don’t have to spend time building out your entire website around a particular plugin or system until you have contributors rolling in to support your business idea.
Which Is the Best Crowdfunding Plugin for WordPress?
Through all of our testing, we’ve found that the best crowdfunding plugin for WordPress is Charitable. It has all the tools you need to set up a fundraising campaign. With the peer-to-peer fundraising capability, you can have ambassadors spread the word and increase your donation amount. Beyond that, you can accept recurring donations, connect them to your newsletter software, and more.
If you just want to simply add a crowdfunding feature to your existing website, WP Simple Pay or WPForms are good, cost-effective solutions. You can add a simple crowdfunding payment form to any part of your website and start raising money.
We hope this article helped you find the best crowdfunding plugins for WordPress. You may also want to check out our list of the best WordPress themes for crowdfunding and our guide on how to increase your blog traffic.
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
Do the Woo 4.0 – WordPress.com News
Editor’s note: This is a guest post from Bob Dunn, founder of Do the Woo, a podcast channel elevating voices of the WooCommerce and WordPress community.
It was early 2023, and I’d been searching for the perfect direction for Do the Woo, the podcast and site we first launched in 2016. I’d made some small steps, but I hadn’t yet found the grand recipe. I just knew that with the shows changing format, the site needed to as well.
Finally, it came to me, as clear as day.
If I was going to do a major site redesign, I wanted it to be built on blocks. I wanted a full-site editor. And I wanted a hosting platform that would take care of things so I could focus on the content. That meant WordPress.com.
So that fall, around the time of WordCamp US, I sent Matt Mullenweg a message. Just as I’d shared ideas with Matt in the past, I did so now—except now was my vision for the next Do the Woo, and the platform I thought it should be built upon. Incredibly, he saw what I saw, and not long after a dream partnership formed: I began working with WordPress.com’s special projects team on the next version of Do the Woo.
Between then and now, a lot has happened. A lot of wireframes, a lot of discussion, a lot of iteration. The WordPress.com team has done incredible work throughout. During my visit to CloudFest in Germany, we even soft-launched the new site. But now it’s official. Today, on the first day of WordCamp Europe, I’m excited to announce Do the Woo 4.0: the podcast by WordPress and WooCommerce builder and business community, for the community.
There are so many things I could tell you about the new site, but it’s all right there on DotheWoo.io, so head over there to learn about our launch. And stay tuned—there’s lots of exciting stuff in the works.
This wouldn’t have happened without the folks from WordPress.com, WooCommerce, and Jetpack. I’m thrilled with what they’ve done with the site, and even more thrilled that my new home is on WordPress.com. I can’t wait for you to join our journey. Let’s do the Woo!
Join 111.3M other subscribers
WORDPRESS
How to Start a Dropshipping Business and Earn $150k/yr: A Step-by-Step Guide
Exposing the Lies of Dropshipping Gurus: How to Start a Dropshipping Business the Right Way
Are you tired of watching countless videos promising to teach you how to start a dropshipping business and make a fortune overnight? Have you followed their advice, only to see your e-commerce store fail miserably? If so, you’re not alone. The truth is, many aspiring entrepreneurs have been misled by dropshipping gurus who claim to have the secret formula for success.
We strongly recommend that you check out our guide on how to take advantage of AI in today’s passive income economy.
Dropshipping gurus often showcase their impressive revenue figures, claiming to have made thousands of dollars in a single day. They promise that anyone can easily replicate their success and start a dropshipping business with minimal effort. However, what they fail to mention is that these results are usually short-lived and unsustainable.
The reality is that building a successful dropshipping business requires far more than just selecting a winning product, setting up a store, and launching a few ads. It involves careful planning, strategic marketing, and exceptional customer service. Unfortunately, most gurus focus solely on the initial stages of starting a dropshipping business, neglecting the crucial aspects that determine long-term success.
The Pitfalls of Following Guru Advice
When you start a dropshipping business based on the advice of gurus, you may experience a brief period of success. You might make a few sales and feel excited about the potential of your new venture. However, this initial success is often followed by a sudden drop in revenue, leaving you confused and frustrated.
The reason for this decline is simple: the strategies taught by most gurus are not designed for long-term sustainability. They focus on short-term tactics, such as running aggressive ad campaigns and testing countless products, without considering the importance of building a strong brand and providing excellent customer service.
The Importance of Customer Satisfaction
One of the most critical factors in running a successful dropshipping business is customer satisfaction. When you start a dropshipping business, your primary goal should be to provide an exceptional experience for your customers. This includes offering high-quality products, timely shipping, and responsive customer support.
Unfortunately, many dropshippers overlook the importance of customer satisfaction in their pursuit of quick profits. They focus solely on driving traffic to their store and making sales, neglecting the needs of their customers once the transaction is complete. As a result, they often face a high number of complaints, refunds, and chargebacks, which can quickly erode their profits and damage their reputation.
Building a Sustainable Dropshipping Business
To start a dropshipping business that stands the test of time, you need to shift your focus from short-term gains to long-term sustainability. This involves investing time and effort into building a strong foundation for your business, rather than chasing the latest trends or relying on questionable tactics.
One of the key elements of a sustainable dropshipping business is a well-defined niche. Instead of trying to sell a wide range of unrelated products, focus on a specific category that aligns with your interests and expertise. This will allow you to establish yourself as an authority in your niche, attract a loyal customer base, and differentiate yourself from competitors.
Another crucial aspect of building a sustainable dropshipping business is branding. Develop a unique brand identity that resonates with your target audience and sets you apart from other dropshippers. This includes creating a professional logo, designing an attractive website, and maintaining a consistent brand voice across all your marketing channels.
Prioritizing Customer Service
To ensure the long-term success of your dropshipping business, you must prioritize customer service. This means going above and beyond to meet the needs and expectations of your customers, even if it requires additional time and effort on your part.
Start by providing clear and detailed product descriptions, including accurate shipping times and return policies. Respond promptly to customer inquiries and complaints, and be proactive in addressing any issues that arise. Consider offering personalized thank-you notes, free gifts, or discounts to show your appreciation for your customers’ business.
By focusing on customer satisfaction, you’ll build a loyal customer base that will not only make repeat purchases but also recommend your business to others. This word-of-mouth marketing can be incredibly valuable in driving sustainable growth for your dropshipping business.
Automating Your Dropshipping Business
As your dropshipping business grows, you may find it challenging to keep up with the increasing demands of customer service and order fulfillment. This is where automation comes into play. By implementing automated systems and tools, you can streamline your operations, reduce manual labor, and focus on scaling your business.
One effective way to automate your dropshipping business is by using a reliable order fulfillment service. These services handle the entire process of storing, packing, and shipping your products, allowing you to focus on marketing and customer service. They also provide real-time tracking information, which can help reduce customer inquiries and improve the overall shopping experience.
Another area where automation can be beneficial is customer support. Implementing a chatbot or a comprehensive FAQ page can help address common customer questions and concerns, freeing up your time to handle more complex issues. You can also use email automation to send personalized order confirmations, shipping updates, and follow-up messages, keeping your customers informed and engaged throughout the buying process.
Starting a dropshipping business can be a lucrative and rewarding venture, but it requires a strategic approach and a long-term mindset. Instead of falling for the empty promises of dropshipping gurus, focus on building a sustainable and customer-centric business that can withstand the test of time.
Begin by carefully selecting your niche and products, ensuring that they align with your interests and target audience. Invest time in creating a strong brand identity and developing a professional website that showcases your unique value proposition. Prioritize customer satisfaction by providing exceptional service, responsive support, and high-quality products.
As you start a dropshipping business and your business grows, continuously monitor your performance and make data-driven decisions to optimize your operations. Implement automation tools and systems to streamline your processes and free up your time to focus on growth and expansion.
Conclusion
In conclusion, starting a successful dropshipping business requires more than just following the advice of self-proclaimed gurus. It demands a commitment to providing value to your customers, building a strong brand, and continuously adapting to the ever-changing e-commerce landscape.
By prioritizing customer satisfaction, focusing on long-term sustainability, and leveraging automation tools, you can start a dropshipping business that not only survives but thrives in the competitive online marketplace. Remember, success in dropshipping is not about chasing quick profits or replicating someone else’s tactics; it’s about creating a business that genuinely serves your customers and stands the test of time.
So, if you’re ready to start a dropshipping business the right way, ignore the hype and focus on the fundamentals. With dedication, hard work, and a customer-centric approach, you can build a profitable and rewarding dropshipping business that you can be proud of.
Frequently Asked Questions (FAQ)
How can a beginner start dropshipping?
A beginner can start a dropshipping business by following these steps:
- Choose a niche and research products that are in demand.
- Find reliable suppliers who offer dropshipping services.
- Create an e-commerce website using platforms like Shopify, WooCommerce, or Magento.
- List your products on your website and set competitive prices.
- Market your store through various channels, such as social media, paid advertising, and email marketing.
- Process orders and coordinate with your suppliers to ship products directly to your customers.
- Provide excellent customer service and continuously optimize your business based on performance data.
How profitable is dropshipping?
The profitability of dropshipping varies depending on several factors, such as your niche, product pricing, marketing strategies, and operational costs. Some dropshippers earn a few hundred dollars per month, while others generate six or even seven-figure incomes. To maximize your profitability, it’s essential to:
- Choose products with healthy profit margins.
- Negotiate favorable terms with your suppliers.
- Optimize your pricing strategy to remain competitive while ensuring profitability.
- Continuously monitor and reduce your operational costs.
- Invest in effective marketing campaigns to drive targeted traffic to your store.
How much do I need to start a dropshipping business?
The cost of starting a dropshipping business can vary greatly depending on your approach and the tools you choose to use. However, here are some general expenses to consider:
- E-commerce platform subscription (e.g., Shopify, WooCommerce): $29 to $299 per month.
- Domain name registration: $10 to $20 per year.
- Website hosting: $10 to $100 per month.
- Product sourcing and samples: $50 to $500, depending on your niche and product types.
- Marketing and advertising: $100 to $1,000 or more per month, depending on your strategies and target audience.
On average, you can expect to invest between $500 to $3,000 to start a basic dropshipping business. However, it’s possible to start with a smaller budget by opting for more affordable tools and focusing on organic marketing strategies.
Can you do dropshipping in Nigeria?
Yes, it is possible to start a dropshipping business in Nigeria. However, there are some challenges and considerations to keep in mind:
- Payment processing: Not all international payment gateways are available in Nigeria, so you may need to use local payment options like Paystack or Flutterwave.
- Shipping and logistics: Shipping times and costs may be higher when dropshipping to Nigeria, so it’s essential to find reliable suppliers and logistics partners who can handle international shipping.
- Import duties and taxes: Be aware of any import duties, taxes, or regulations that may apply to your products when shipping to Nigeria.
- Internet connectivity: Ensure that you have a stable internet connection to manage your online store and communicate with suppliers and customers.
- Market demand: Research the Nigerian market to identify products that are in demand and can be profitably dropshipped to the country.
Despite these challenges, dropshipping in Nigeria can be a viable business opportunity, especially if you focus on serving the local market and adapting your strategies to the specific needs and preferences of Nigerian consumers.
We strongly recommend that you check out our guide on how to take advantage of AI in today’s passive income economy.
WORDPRESS
Making a WordPress plugin extensible with PHP classes
WordPress plugins can be extended with additional functionality, as demonstrated by popular plugins like WooCommerce and Gravity Forms. In the article “Architecting a WordPress plugin to support extensions,” we learn there are two primary ways to make a WordPress plugin extensible:
- By setting up hooks (actions and filters) for extension plugins to inject their own functionality
- By providing PHP classes that extension plugins can inherit
The first method relies more on documentation, detailing available hooks and their usage. The second method, by contrast, offers ready-to-use code for extensions, reducing the need for extensive documentation. This is advantageous because creating documentation alongside code can complicate the plugin’s management and release.
Providing PHP classes directly effectively replaces documentation with code. Instead of teaching how to implement a feature, the plugin supplies the necessary PHP code, simplifying the task for third-party developers.
Let’s explore some techniques for achieving this, with the ultimate goal of fostering an ecosystem of integrations around our WordPress plugin.
Defining base PHP classes in the WordPress plugin
The WordPress plugin will include PHP classes intended for use by extension plugins. These PHP classes might not be used by the main plugin itself but are provided specifically for others to use.
Let’s see how this is implemented in the open-source Gato GraphQL plugin.
AbstractPlugin class:
AbstractPlugin
represents a plugin, both for the main Gato GraphQL plugin and its extensions:
abstract class AbstractPlugin implements PluginInterface
{
protected string $pluginBaseName;
protected string $pluginSlug;
protected string $pluginName;
public function __construct(
protected string $pluginFile,
protected string $pluginVersion,
?string $pluginName,
) {
$this->pluginBaseName = plugin_basename($pluginFile);
$this->pluginSlug = dirname($this->pluginBaseName);
$this->pluginName = $pluginName ?? $this->pluginBaseName;
}
public function getPluginName(): string
{
return $this->pluginName;
}
public function getPluginBaseName(): string
{
return $this->pluginBaseName;
}
public function getPluginSlug(): string
{
return $this->pluginSlug;
}
public function getPluginFile(): string
{
return $this->pluginFile;
}
public function getPluginVersion(): string
{
return $this->pluginVersion;
}
public function getPluginDir(): string
{
return dirname($this->pluginFile);
}
public function getPluginURL(): string
{
return plugin_dir_url($this->pluginFile);
}
// ...
}
AbstractMainPlugin class:
AbstractMainPlugin
extends AbstractPlugin
to represent the main plugin:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface
{
public function __construct(
string $pluginFile,
string $pluginVersion,
?string $pluginName,
protected MainPluginInitializationConfigurationInterface $pluginInitializationConfiguration,
) {
parent::__construct(
$pluginFile,
$pluginVersion,
$pluginName,
);
}
// ...
}
AbstractExtension class:
Similarly, AbstractExtension
extends AbstractPlugin
to represent an extension plugin:
abstract class AbstractExtension extends AbstractPlugin implements ExtensionInterface
{
public function __construct(
string $pluginFile,
string $pluginVersion,
?string $pluginName,
protected ?ExtensionInitializationConfigurationInterface $extensionInitializationConfiguration,
) {
parent::__construct(
$pluginFile,
$pluginVersion,
$pluginName,
);
}
// ...
}
Notice that AbstractExtension
is included within the main plugin, providing functionality to register and initialize an extension. However, it is only used by extensions, not by the main plugin itself.
The AbstractPlugin
class contains shared initialization code invoked at different times. These methods are defined at the ancestor level but are invoked by the inheriting classes according to their lifecycles.
The main plugin and extensions are initialized by executing the setup
method on the corresponding class, invoked from within the main WordPress plugin file.
For instance, in Gato GraphQL, this is done in gatographql.php
:
$pluginFile = __FILE__;
$pluginVersion = '2.4.0';
$pluginName = __('Gato GraphQL', 'gatographql');
PluginApp::getMainPluginManager()->register(new Plugin(
$pluginFile,
$pluginVersion,
$pluginName
))->setup();
setup method:
At the ancestor level, setup
contains the common logic between the plugin and its extensions, such as unregistering them when the plugin is deactivated. This method is not final; It can be overridden by the inheriting classes to add their functionality:
abstract class AbstractPlugin implements PluginInterface
{
// ...
public function setup(): void
{
register_deactivation_hook(
$this->getPluginFile(),
$this->deactivate(...)
);
}
public function deactivate(): void
{
$this->removePluginVersion();
}
private function removePluginVersion(): void
{
$pluginVersions = get_option('gatographql-plugin-versions', []);
unset($pluginVersions[$this->pluginBaseName]);
update_option('gatographql-plugin-versions', $pluginVersions);
}
}
Main plugin’s setup method:
The main plugin’s setup
method initializes the application’s lifecycle. It executes the main plugin’s functionality through methods like initialize
, configureComponents
, configure
, and boot
, and triggers corresponding action hooks for extensions:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface
{
public function setup(): void
{
parent::setup();
add_action('plugins_loaded', function (): void
{
// 1. Initialize main plugin
$this->initialize();
// 2. Initialize extensions
do_action('gatographql:initializeExtension');
// 3. Configure main plugin components
$this->configureComponents();
// 4. Configure extension components
do_action('gatographql:configureExtensionComponents');
// 5. Configure main plugin
$this->configure();
// 6. Configure extension
do_action('gatographql:configureExtension');
// 7. Boot main plugin
$this->boot();
// 8. Boot extension
do_action('gatographql:bootExtension');
}
// ...
}
// ...
}
Extension setup method:
The AbstractExtension
class executes its logic on the corresponding hooks:
abstract class AbstractExtension extends AbstractPlugin implements ExtensionInterface
{
// ...
final public function setup(): void
{
parent::setup();
add_action('plugins_loaded', function (): void
{
// 2. Initialize extensions
add_action(
'gatographql:initializeExtension',
$this->initialize(...)
);
// 4. Configure extension components
add_action(
'gatographql:configureExtensionComponents',
$this->configureComponents(...)
);
// 6. Configure extension
add_action(
'gatographql:configureExtension',
$this->configure(...)
);
// 8. Boot extension
add_action(
'gatographql:bootExtension',
$this->boot(...)
);
}, 20);
}
}
Methods initialize
, configureComponents
, configure
, and boot
are common to both the main plugin and extensions and may share logic. This shared logic is stored in the AbstractPlugin
class.
For example, the configure
method configures the plugin or extensions, calling callPluginInitializationConfiguration
, which has different implementations for the main plugin and extensions and is defined as abstract and getModuleClassConfiguration
, which provides a default behavior but can be overridden if needed:
abstract class AbstractPlugin implements PluginInterface
{
// ...
public function configure(): void
{
$this->callPluginInitializationConfiguration();
$appLoader = App::getAppLoader();
$appLoader->addModuleClassConfiguration($this->getModuleClassConfiguration());
}
abstract protected function callPluginInitializationConfiguration(): void;
/**
* @return array,mixed> [key]: Module class, [value]: Configuration
*/
public function getModuleClassConfiguration(): array
{
return [];
}
}
The main plugin provides its implementation for callPluginInitializationConfiguration
:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface
{
// ...
protected function callPluginInitializationConfiguration(): void
{
$this->pluginInitializationConfiguration->initialize();
}
}
Similarly, the extension class provides its implementation:
abstract class AbstractExtension extends AbstractPlugin implements ExtensionInterface
{
// ...
protected function callPluginInitializationConfiguration(): void
{
$this->extensionInitializationConfiguration?->initialize();
}
}
Methods initialize
, configureComponents
and boot
are defined at the ancestor level and can be overridden by inheriting classes:
abstract class AbstractPlugin implements PluginInterface
{
// ...
public function initialize(): void
{
$moduleClasses = $this->getModuleClassesToInitialize();
App::getAppLoader()->addModuleClassesToInitialize($moduleClasses);
}
/**
* @return array> List of `Module` class to initialize
*/
abstract protected function getModuleClassesToInitialize(): array;
public function configureComponents(): void
{
$classNamespace = ClassHelpers::getClassPSR4Namespace(get_called_class());
$moduleClass = $classNamespace . '\Module';
App::getModule($moduleClass)->setPluginFolder(dirname($this->pluginFile));
}
public function boot(): void
{
// By default, do nothing
}
}
All methods can be overridden by AbstractMainPlugin
or AbstractExtension
to extend them with their custom functionality.
For the main plugin, the setup
method also removes any caching from the WordPress instance when the plugin or any of its extensions is activated or deactivated:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface
{
public function setup(): void
{
parent::setup();
// ...
// Main-plugin specific methods
add_action(
'activate_plugin',
function (string $pluginFile): void {
$this->maybeRegenerateContainerWhenPluginActivatedOrDeactivated($pluginFile);
}
);
add_action(
'deactivate_plugin',
function (string $pluginFile): void {
$this->maybeRegenerateContainerWhenPluginActivatedOrDeactivated($pluginFile);
}
);
}
public function maybeRegenerateContainerWhenPluginActivatedOrDeactivated(string $pluginFile): void
{
// Removed code for simplicity
}
// ...
}
Similarly, the deactivate
method removes caching and boot
executes additional action hooks for the main plugin only:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface
{
public function deactivate(): void
{
parent::deactivate();
$this->removeTimestamps();
}
protected function removeTimestamps(): void
{
$userSettingsManager = UserSettingsManagerFacade::getInstance();
$userSettingsManager->removeTimestamps();
}
public function boot(): void
{
parent::boot();
add_filter(
'admin_body_class',
function (string $classes): string {
$extensions = PluginApp::getExtensionManager()->getExtensions();
$commercialExtensionActivatedLicenseObjectProperties = SettingsHelpers::getCommercialExtensionActivatedLicenseObjectProperties();
foreach ($extensions as $extension) {
$extensionCommercialExtensionActivatedLicenseObjectProperties = $commercialExtensionActivatedLicenseObjectProperties[$extension->getPluginSlug()] ?? null;
if ($extensionCommercialExtensionActivatedLicenseObjectProperties === null) {
continue;
}
return $classes . ' is-gatographql-customer';
}
return $classes;
}
);
}
}
From all the code presented above, it is clear that when designing and coding a WordPress plugin, we need to consider the needs of its extensions and reuse code across them as much as possible. Implementing sound Object-Oriented Programming patterns (such as the SOLID principles) helps achieve this, making the codebase maintainable for the long term.
Declaring and validating the version dependency
Since the extension inherits from a PHP class provided by the plugin, it’s crucial to validate that the required version of the plugin is present. Failing to do so could cause conflicts that bring the site down.
For example, if the AbstractExtension
class is updated with breaking changes and releases a major version 4.0.0
from the previous 3.4.0
, loading the extension without checking the version could result in a PHP error, preventing WordPress from loading.
To avoid this, the extension must validate that the installed plugin is version 3.x.x
. When version 4.0.0
is installed, the extension will be disabled, thus preventing errors.
The extension can accomplish this validation using the following logic, executed on the plugins_loaded
hook (since the main plugin will be loaded by then) in the extension’s main plugin file. This logic accesses the ExtensionManager
class, which is included in the main plugin to manage extensions:
/**
* Create and set-up the extension
*/
add_action(
'plugins_loaded',
function (): void {
/**
* Extension's name and version.
*
* Use a stability suffix as supported by Composer.
*/
$extensionVersion = '1.1.0';
$extensionName = __('Gato GraphQL - Extension Template');
/**
* The minimum version required from the Gato GraphQL plugin
* to activate the extension.
*/
$gatoGraphQLPluginVersionConstraint="^1.0";
/**
* Validate Gato GraphQL is active
*/
if (!class_exists(GatoGraphQLGatoGraphQLPlugin::class)) {
add_action('admin_notices', function () use ($extensionName) {
printf(
'',
sprintf(
__('Plugin %s is not installed or activated. Without it, plugin %s will not be loaded.'),
__('Gato GraphQL'),
$extensionName
)
);
});
return;
}
$extensionManager = GatoGraphQLGatoGraphQLPluginApp::getExtensionManager();
if (!$extensionManager->assertIsValid(
GatoGraphQLExtension::class,
$extensionVersion,
$extensionName,
$gatoGraphQLPluginVersionConstraint
)) {
return;
}
// Load Composer’s autoloader
require_once(__DIR__ . '/vendor/autoload.php');
// Create and set-up the extension instance
$extensionManager->register(new GatoGraphQLExtension(
__FILE__,
$extensionVersion,
$extensionName,
))->setup();
}
);
Notice how the extension declares a dependency on version constraint ^1.0
of the main plugin (using Composer’s version constraints). Thus, when version 2.0.0
of Gato GraphQL is installed, the extension will not be activated.
The version constraint is validated via the ExtensionManager::assertIsValid
method, which calls Semver::satisfies
(provided by the composer/semver
package):
use ComposerSemverSemver;
class ExtensionManager extends AbstractPluginManager
{
/**
* Validate that the required version of the Gato GraphQL for WP plugin is installed.
*
* If the assertion fails, it prints an error on the WP admin and returns false
*
* @param string|null $mainPluginVersionConstraint the semver version constraint required for the plugin (eg: "^1.0" means >=1.0.0 and getPlugin();
$mainPluginVersion = $mainPlugin->getPluginVersion();
if (
$mainPluginVersionConstraint !== null && !Semver::satisfies(
$mainPluginVersion,
$mainPluginVersionConstraint
)
) {
$this->printAdminNoticeErrorMessage(
sprintf(
__('Extension or bundle %s requires plugin %s to satisfy version constraint %s
, but the current version %s
does not. The extension or bundle has not been loaded.', 'gatographql'),
$extensionName ?? $extensionClass,
$mainPlugin->getPluginName(),
$mainPluginVersionConstraint,
$mainPlugin->getPluginVersion(),
)
);
return false;
}
return true;
}
protected function printAdminNoticeErrorMessage(string $errorMessage): void
{
add_action('admin_notices', function () use ($errorMessage): void {
$adminNotice_safe = sprintf(
'',
$errorMessage
);
echo $adminNotice_safe;
});
}
}
Running integration tests against a WordPress server
To make it easier for third-party developers to create extensions for your plugins, provide them with tools for development and testing, including workflows for their continuous integration and continuous delivery (CI/CD) processes.
During development, anyone can easily spin up a web server using DevKinsta, install the plugin for which they are coding the extension, and immediately validate that the extension is compatible with the plugin.
To automate testing during CI/CD, we need to have the web server accessible over a network to the CI/CD service. Services such as InstaWP can create a sandbox site with WordPress installed for this purpose.
If the extension’s codebase is hosted on GitHub, developers can use GitHub Actions to run integration tests against the InstaWP service. The following workflow installs the extension on an InstaWP sandbox site (alongside the latest stable version of the main plugin) and then runs the integration tests:
name: Integration tests (InstaWP)
on:
workflow_run:
workflows: [Generate plugins]
types:
- completed
jobs:
provide_data:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
name: Retrieve the GitHub Action artifact URLs to install in InstaWP
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: 8.1
coverage: none
env:
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: "ramsey/composer-install@v2"
- name: Retrieve artifact URLs from GitHub workflow
uses: actions/github-script@v6
id: artifact-url
with:
script: |
const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
const artifactURLs = allArtifacts.data.artifacts.map((artifact) => {
return artifact.url.replace('https://api.github.com/repos', 'https://nightly.link') + '.zip'
}).concat([
"https://downloads.wordpress.org/plugin/gatographql.latest-stable.zip"
]);
return artifactURLs.join(',');
result-encoding: string
- name: Artifact URL for InstaWP
run: echo "Artifact URL for InstaWP - ${{ steps.artifact-url.outputs.result }}"
shell: bash
outputs:
artifact_url: ${{ steps.artifact-url.outputs.result }}
process:
needs: provide_data
name: Launch InstaWP site from template 'integration-tests' and execute integration tests against it
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: 8.1
coverage: none
env:
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: "ramsey/composer-install@v2"
- name: Create InstaWP instance
uses: instawp/wordpress-testing-automation@main
id: create-instawp
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INSTAWP_TOKEN: ${{ secrets.INSTAWP_TOKEN }}
INSTAWP_TEMPLATE_SLUG: "integration-tests"
REPO_ID: 25
INSTAWP_ACTION: create-site-template
ARTIFACT_URL: ${{ needs.provide_data.outputs.artifact_url }}
- name: InstaWP instance URL
run: echo "InstaWP instance URL - ${{ steps.create-instawp.outputs.instawp_url }}"
shell: bash
- name: Extract InstaWP domain
id: extract-instawp-domain
run: |
instawp_domain="$(echo "${{ steps.create-instawp.outputs.instawp_url }}" | sed -e s#https://##)"
echo "instawp-domain=$(echo $instawp_domain)" >> $GITHUB_OUTPUT
- name: Run tests
run: |
INTEGRATION_TESTS_WEBSERVER_DOMAIN=${{ steps.extract-instawp-domain.outputs.instawp-domain }}
INTEGRATION_TESTS_AUTHENTICATED_ADMIN_USER_USERNAME=${{ steps.create-instawp.outputs.iwp_wp_username }}
INTEGRATION_TESTS_AUTHENTICATED_ADMIN_USER_PASSWORD=${{ steps.create-instawp.outputs.iwp_wp_password }}
vendor/bin/phpunit --filter=Integration
- name: Destroy InstaWP instance
uses: instawp/wordpress-testing-automation@main
id: destroy-instawp
if: ${{ always() }}
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INSTAWP_TOKEN: ${{ secrets.INSTAWP_TOKEN }}
INSTAWP_TEMPLATE_SLUG: "integration-tests"
REPO_ID: 25
INSTAWP_ACTION: destroy-site
This workflow accesses the .zip file via Nightly Link, a service that allows accessing an artifact from GitHub without logging in, simplifying the configuration of InstaWP.
Releasing the extension plugin
We can provide tools to help release the extensions, automating the procedures as much as possible.
The Monorepo Builder is a library for managing any PHP project, including a WordPress plugin. It provides the monorepo-builder release
command to release a version of the project, incrementing either the major, minor, or patch component of the version according to semantic versioning.
This command executes a series of release workers, which are PHP classes that execute certain logic. The default workers include one that creates a git tag
with the new version and another that pushes the tag to the remote repository. Custom workers can be injected before, after, or in between these steps.
The release workers are configured via a configuration file:
use SymplifyMonorepoBuilderConfigMBConfig;
use SymplifyMonorepoBuilderReleaseReleaseWorkerAddTagToChangelogReleaseWorker;
use SymplifyMonorepoBuilderReleaseReleaseWorkerPushNextDevReleaseWorker;
use SymplifyMonorepoBuilderReleaseReleaseWorkerPushTagReleaseWorker;
use SymplifyMonorepoBuilderReleaseReleaseWorkerSetCurrentMutualDependenciesReleaseWorker;
use SymplifyMonorepoBuilderReleaseReleaseWorkerSetNextMutualDependenciesReleaseWorker;
use SymplifyMonorepoBuilderReleaseReleaseWorkerTagVersionReleaseWorker;
use SymplifyMonorepoBuilderReleaseReleaseWorkerUpdateBranchAliasReleaseWorker;
use SymplifyMonorepoBuilderReleaseReleaseWorkerUpdateReplaceReleaseWorker;
return static function (MBConfig $mbConfig): void {
// release workers - in order to execute
$mbConfig->workers([
UpdateReplaceReleaseWorker::class,
SetCurrentMutualDependenciesReleaseWorker::class,
AddTagToChangelogReleaseWorker::class,
TagVersionReleaseWorker::class,
PushTagReleaseWorker::class,
SetNextMutualDependenciesReleaseWorker::class,
UpdateBranchAliasReleaseWorker::class,
PushNextDevReleaseWorker::class,
]);
};
We can provide custom release workers to augment the release process tailored to the needs of a WordPress plugin. For example, the InjectStableTagVersionInPluginReadmeFileReleaseWorker
sets the new version as the “Stable tag” entry in the extension’s readme.txt file:
use NetteUtilsStrings;
use PharIoVersionVersion;
use SymplifySmartFileSystemSmartFileInfo;
use SymplifySmartFileSystemSmartFileSystem;
class InjectStableTagVersionInPluginReadmeFileReleaseWorker implements ReleaseWorkerInterface
{
public function __construct(
// This class is provided by the Monorepo Builder
private SmartFileSystem $smartFileSystem,
) {
}
public function getDescription(Version $version): string
{
return 'Have the "Stable tag" point to the new version in the plugin's readme.txt file';
}
public function work(Version $version): void
{
$replacements = [
'/Stable tag:s+[a-z0-9.-]+/' => 'Stable tag: ' . $version->getVersionString(),
];
$this->replaceContentInFiles(['/readme.txt'], $replacements);
}
/**
* @param string[] $files
* @param array $regexPatternReplacements regex pattern to search, and its replacement
*/
protected function replaceContentInFiles(array $files, array $regexPatternReplacements): void
{
foreach ($files as $file) {
$fileContent = $this->smartFileSystem->readFile($file);
foreach ($regexPatternReplacements as $regexPattern => $replacement) {
$fileContent = Strings::replace($fileContent, $regexPattern, $replacement);
}
$this->smartFileSystem->dumpFile($file, $fileContent);
}
}
}
By adding InjectStableTagVersionInPluginReadmeFileReleaseWorker
to the configuration list, whenever executing the monorepo-builder release
command to release a new version of the plugin, the “Stable tag” in the extension’s readme.txt file will be automatically updated.
Publishing the extension plugin to the WP.org directory
We can also distribute a workflow to help release the extension to the WordPress Plugin Directory. When tagging the project on the remote repository, the following workflow will publish the WordPress extension plugin to the directory:
# See: https://github.com/10up/action-wordpress-plugin-deploy#deploy-on-pushing-a-new-tag
name: Deploy to WordPress.org Plugin Directory (SVN)
on:
push:
tags:
- "*"
jobs:
tag:
name: New tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: WordPress Plugin Deploy
uses: 10up/action-wordpress-plugin-deploy@stable
env:
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
SLUG: ${{ secrets.SLUG }}
This workflow uses the 10up/action-wordpress-plugin-deploy
action, which retrieves the code from a Git repository and pushes it to the WordPress.org SVN repository, simplifying the operation.
Summary
When creating an extensible plugin for WordPress, our goal is to make it as easy as possible for third-party developers to extend it, thereby maximizing the chances of fostering a vibrant ecosystem around our plugins.
While providing extensive documentation can guide developers on how to extend the plugin, an even more effective approach is to supply the necessary PHP code and tooling for development, testing, and releasing their extensions.
By including the additional code needed by extensions directly in our plugin, we simplify the process for developers.
Do you plan to make your WordPress plugin extensible? Let us know in the comments section.
-
SEO6 days ago
8 Ways To Promote Your Facebook Page Successfully
-
SEARCHENGINES6 days ago
Google Search Ranking Algorithm Volatility On June 8th
-
SEARCHENGINES5 days ago
Daily Search Forum Recap: June 10, 2024
-
SEO5 days ago
Google’s Statement About CTR And HCU
-
WORDPRESS3 days ago
How to Start a Dropshipping Business and Earn $150k/yr: A Step-by-Step Guide
-
SEO5 days ago
How to Persuade Your Boss to Send You to Ahrefs Evolve
-
AFFILIATE MARKETING7 days ago
Father’s Day Gift: Get Microsoft Project for Just $20
-
WORDPRESS5 days ago
A Small Business Guide to Building An E-Commerce Website | CO