I have been building on WordPress since 2008. Themes, plugins, custom post types, REST API integrations, multisite networks, WooCommerce stores. Hundreds of projects across nearly two decades. And until today, I had never published a single plugin on WordPress.org.
That changed this morning. SampleHQ Request Form is now live in the WordPress plugin directory. It is a free, standalone plugin for collecting product sample requests. And building it taught me more about WordPress development standards than the previous 18 years combined.
Why It Took 18 Years
The honest answer: I never needed to. Every WordPress project I built was for a specific client or a specific business. The code lived in private repositories, deployed to specific servers, maintained for specific people. There was no reason to generalize it for public distribution.
Publishing on WordPress.org is a different discipline. Your code runs on servers you will never see, inside configurations you cannot predict, alongside plugins you have never heard of. The standards exist because they have to. When 43% of the web runs on WordPress, a sloppy plugin is not just your problem.
The reason I finally did it is SampleHQ. The platform I have been building as a multi-tenant SaaS needed a way for WordPress users to collect sample requests without signing up for the full platform first. A free plugin that works standalone, with an optional connection to SampleHQ for teams that need CRM integration, fulfillment tracking, and analytics.
What the Plugin Does
The core problem: businesses that ship physical product samples have no good way to collect structured requests. Generic form plugins give you text fields. But a sample request is not a contact form. It has products with SKUs and images, quantities, shipping addresses, and selections from a catalog.
SampleHQ Request Form includes a built-in sample library where you manage products with categories, images, SKUs, and descriptions. The form builder has 17 field types, including a sample picker that lets visitors browse your catalog, filter by category, and select products with quantities. It is structured data from the start, not free text that someone has to parse later.
The form builder is drag-and-drop with multi-column layouts, conditional logic, and a multi-step wizard mode. You embed forms with a Gutenberg block, Elementor widget, or shortcode. Submissions land in a dashboard where you can search, filter, star, and export to CSV.
For WordPress sites already running WooCommerce, the plugin can use WooCommerce products as the sample catalog instead of maintaining a separate library. It adds a "Request a Sample" button to product pages and handles the form rendering in a modal.
Everything works without an external account. No API keys, no SaaS dependency, no feature gates. The optional SampleHQ connection syncs submissions and catalog data to the platform for teams that need more than what a WordPress plugin can provide.
What the Review Process Taught Me
The plugin went through six versions before the WordPress.org review team approved it. That is not a complaint. Every piece of feedback made the plugin better, and several issues were things I would have missed in a private deployment.
The review flagged inline JavaScript event handlers. I had used them in a few admin views. The fix was extracting all inline scripts into properly enqueued external JS files. Standard practice, but easy to skip when you control the environment.
They caught a CSS injection feature I had included for form appearance customization. It let admins enter arbitrary CSS. On a single-site install where the admin is the owner, that is fine. On a multisite where admins might be tenants with limited trust, it is a stored XSS vector. I removed it and replaced it with a fixed set of CSS custom properties for theming.
File upload validation needed tightening. I was checking MIME types but not using is_uploaded_file() to verify the file came from an actual HTTP upload. The review caught that. They also flagged that I was not recursively sanitizing JSON when importing form configurations, which could have been a vector for injecting unsanitized data into the database.
The redirect handling needed wp_safe_redirect() instead of wp_redirect() with an allowed_redirect_hosts filter. Admin notices needed scoping to plugin pages only. The sslverify flag in a self-check HTTP request needed to be removed.
Every fix was legitimate. The review process is what separates WordPress.org plugins from the wild west of zip files downloaded from random websites. After 18 years of building WordPress code that only I reviewed, having someone else audit it with security-first thinking was humbling and educational.
Architecture Decisions Worth Noting
A few choices that might be useful if you are building a WordPress plugin in 2026.
Custom tables instead of custom post types. The plugin uses eight custom database tables for samples, categories, forms, submissions, and rate limits. CPTs are great for content, but structured operational data with relational queries, proper indexing, and clean joins works better in custom tables. The plugin includes a versioned migration system that handles schema changes across updates.
React for the builder, vanilla JS for the frontend. The form builder is a full React application using @dnd-kit for drag-and-drop and @wordpress/scripts for the build pipeline. But the public-facing form is server-rendered PHP enhanced with vanilla JavaScript. No React runtime on the frontend. The form works without JavaScript for basic submissions. Progressive enhancement, not a JavaScript dependency.
Form tokens instead of nonces for CSRF. WordPress nonces are tied to user sessions. Public forms have no user session. The plugin generates transient-based form tokens with 24-hour TTL and one-time consumption to prevent replay attacks. Combined with a honeypot field and IP-based rate limiting, this handles spam without requiring a third-party CAPTCHA. Cloudflare Turnstile is available as an optional layer.
PSR-4 autoloading without Composer in production. The plugin registers a custom autoloader that maps the SampleHQForm namespace to the src/ directory. Composer is used for development tooling (PHPStan, PHPCS, testing) but no vendor/ directory ships with the plugin. This avoids the dependency collision problem that plagues WordPress plugins sharing Composer packages.
The Testing Infrastructure
One thing I insisted on from the start: proper test coverage. The plugin has 909 unit tests, 29 integration tests running against a real WordPress instance via wp-env, and 33 Playwright end-to-end test files covering the admin UI, frontend forms, accessibility, responsive behavior, and WooCommerce integration.
For a free WordPress plugin, that might seem excessive. It is not. The plugin runs on servers I cannot access, inside configurations I cannot predict. The test suite is the only way to ship updates with confidence. Every WordPress.org review cycle involved code changes that could have introduced regressions. The tests caught several.
What Comes Next
The plugin is version 1.0.5 on WordPress.org. The GitHub repository is public. Issues, pull requests, and feature requests are welcome.
The immediate roadmap includes more field types, form analytics in the dashboard, and deeper WooCommerce integration. The longer-term goal is making this the standard way WordPress sites collect sample requests, with a clear upgrade path to the full SampleHQ workflow for teams that outgrow what a plugin can do.
After 18 years, publishing something on WordPress.org felt like a milestone. Not because the technology is new, but because the mindset is different. Building for one client is about solving their problem. Building for the directory is about solving the problem correctly for everyone. That distinction took me too long to appreciate.
SampleHQ is the platform behind this plugin. For teams that need CRM integration, fulfillment tracking, and revenue attribution on top of sample requests, the plugin connects with one click.
Top comments (0)