WordPress Engineering

Custom WordPress plugin development

A bespoke plugin is the one part of a WordPress site that nothing else updates. That single fact decides how it should be built, documented and tested — and it is what most plugin projects underestimate.

The problem

The plugin you commission is the code nobody else maintains

Everything else on the site is updated by its author. A custom plugin is updated by whoever you have, on whatever schedule you decide, and it has to survive the WordPress releases, PHP versions and plugin updates that happen around it. A plugin that works on delivery and breaks in a year has not failed at the point of failure — it failed at the point of design.

  • A business rule exists that no available plugin implements correctly
  • Several plugins are being combined to approximate one behaviour
  • An integration is being done by hand because nothing connects the two systems
  • The site's data belongs somewhere WordPress does not put it by default
  • An existing bespoke plugin has been inherited and nobody can safely change it
  • A previous plugin was delivered without documentation and cannot be extended
  • A licensed plugin is being paid for and does not do what is needed
  • The requirement is real but no commercially available plugin covers it
Who this is for

The people who usually bring us this problem

Someone combining plugins to get one behaviour

Three plugins and some custom code are approximating what one clearly-scoped plugin should do.

Someone integrating two systems

WordPress has to exchange data with a CRM, an ERP, a fulfilment system or an internal API.

Someone who inherited a plugin they cannot touch

It works and nobody can safely modify it, and it is now a risk to the site rather than an asset.

What it costs

What this costs while it goes unfixed

Engineering faults are rarely confined to the engineering layer. These are the commercial consequences we see most often.

Nothing updates a custom plugin but you

WordPress, PHP and the plugins around it all move. A bespoke plugin has to keep working across those changes with nobody's author to help, which means it has to be written to standards, tested where it is fragile, and documented well enough for someone else to read.

The data model is the decision that is hard to change

Where the plugin's data lives — custom tables, custom post types, taxonomy, post meta, or an external service — determines how the plugin performs at scale, how it is queried, and how hard it is to move later. It is usually decided in the first week and revisited rarely.

A plugin in the admin is a plugin with access

It executes with the site's own privileges, is reachable from the public internet wherever it registers an endpoint, and can be a way in if it is careless about input, capability checks and nonces. That is a property of the category, not of badly written code specifically.

Undocumented bespoke code becomes unmaintainable

Not because it is bad, but because the next person cannot establish what is deliberate. This is how a plugin that does exactly what is needed becomes the reason a site cannot be updated.

What we do about it

Capabilities

Each of these is work we carry out, not an area we advise on.

Scope definition against the actual requirement

Establishing what the plugin must do, what it must not, and where the boundary with plugins that already exist falls. A surprising number of plugin projects are a scope problem — the requirement is real and exists because three plugins are being asked to do something none of them was built for.

Data model design

Deciding where the data belongs: custom tables for volume and query patterns, post types and taxonomies for content editors manage, post meta for values attached to content, options for configuration, or an external system for data that belongs to one. Chosen deliberately, with the access patterns known.

Admin interfaces that match WordPress

Screens built with the WordPress admin's own components, so the plugin looks and behaves like the rest of the site's administration. A custom interface in a custom style is a place where editors make mistakes, and it is also a place where output has to be escaped.

Integrations and API work

Exchanging data with external systems: authentication, mapping between the two models, error handling and what happens when the other end is unavailable. The failure behaviour is usually the part that is not specified and the part that decides whether the integration is trustworthy.

WordPress coding standards and review

Code written to WordPress's own standards, with the review covering input sanitisation, output escaping, capability checks, nonce verification and database access through the provided APIs. This is what making a plugin safe looks like in ordinary work, and it is not the same thing as a security audit.

Update and compatibility strategy

How the plugin behaves across WordPress, PHP and dependency updates: what is tested, what version ranges are declared, and what happens to the site if the plugin is not updated. Designing for the updates that will happen to the site around it is the difference between a plugin and a liability.

Uninstall, migration and data handling

What happens when the plugin is deactivated, and what happens to its data. A plugin that leaves tables and options behind on removal is one that never fully leaves, and one that deletes data on deactivation is worse.

Documentation and handover

What the plugin does, where its data lives, what is safe to change, what is fragile and why. Written for whoever maintains the site next — which may be us, may be another team, and may be someone who has not been hired yet.

How we work

Engineering methodology

The sequence is deliberate. The order is usually what determines whether the work holds or has to be repeated.

  1. Establish whether the plugin is the right answer

    Sometimes it is not a plugin but a configuration, an existing plugin extending properly, or a change to a process. Saying so is part of the work; commissioning bespoke code to solve a problem that has a supported solution creates a maintenance burden for no reason.

  2. Design the data model before writing behaviour

    Where the data lives determines how everything else is written and how the plugin behaves under volume. Deciding it first, with the access patterns known, is what prevents a plugin that works at a hundred records and cannot be used at ten thousand.

  3. Build in the site it is for

    A plugin developed in isolation meets the real site's theme, plugins and hosting configuration at the worst possible moment. Development happens against the site, including the awkward parts.

  4. Handle the failure cases explicitly

    The external system is down, the input is malformed, the user lacks the capability, the record was deleted between the read and the write. Specifying these is what makes the plugin trustworthy, and they are the behaviours nobody demonstrates.

  5. Test the paths that are fragile, and say which they are

    Where the plugin's correctness depends on a WordPress behaviour that could change, or on an external system's response, that is tested and named. Not everything needs a test suite; the things that would fail silently do.

  6. Document for the next person, not for the delivery

    Documentation is written for whoever maintains the site after the engagement, and it is part of the deliverable rather than an extra. Undocumented bespoke code is a plugin that cannot be safely changed, which is a plugin that becomes a reason not to update the site.

Deliverables

What an engagement produces

Documentation is a deliverable, not an afterthought. On most of these engagements a large part of the value is a defect report precise enough for another team to act on.

Scoping

  • What the plugin does, and what it deliberately does not
  • Whether a custom plugin is the right answer, with the alternative stated if not
  • Data model, with the access patterns it is designed for
  • Where it interacts with existing plugins and where it must not
  • What is fragile, and what would have to change if the requirement grows

Build

  • Plugin written to WordPress coding standards
  • Admin screens built with the WordPress admin's own components
  • Input sanitised, output escaped, capabilities and nonces checked, database access through the provided APIs
  • Explicit handling of failure cases, including the external system being unavailable
  • Uninstall behaviour and data handling defined

Handover

  • What the plugin does, in plain language
  • Where its data lives and how to inspect it
  • What is safe to change and what is fragile
  • Which WordPress, PHP and dependency versions were tested
  • What is documented for whoever maintains it next
Under the hood

Architecture and technology

Where a plugin's data can live

  • Custom database tables, for volume and specific query patterns
  • Custom post types, where editors manage the records as content
  • Taxonomies, where records need to be grouped and filtered
  • Post meta, for values attached to existing content
  • Options, for configuration and small amounts of state
  • An external system, where the data belongs to something else

What a plugin must get right

  • Input sanitised on the way in
  • Output escaped on the way out, in every context it is rendered
  • Capability checks on every action, not only on the screen
  • Nonce verification for anything that changes state
  • Database access through the provided APIs, with prepared statements
  • Behaviour when an external dependency is unavailable
  • What happens to its data on deactivation and removal
Adjacent problems

If this is not quite your problem

These overlap at the edges. Sending you to the right page is more useful than having you work it out.

The site needs building as well as the plugin

Themes, templates, integrations and the plugin work alongside them.

WordPress development

You inherited a plugin you cannot change

Assessment of existing bespoke code and what can safely be done with it.

WordPress maintenance

You want the plugin's security posture examined properly

A scoped review with a defined depth, which is a different piece of work from building.

Website security

The bespoke software is not a plugin

Application-level engineering where the requirement sits outside WordPress's extension points.

Web engineering
Questions

Frequently asked

Will the plugin be security-audited?

Not by default, and we will not describe ordinary review as an audit. The code is written to WordPress coding standards and reviewed for input sanitisation, output escaping, capability checks, nonce verification and database access — which is the standard a plugin has to meet and is not the same thing as an audit. An audit is a separate, scoped piece of work with a defined depth and a written report, and it can be commissioned alongside the build or afterwards. If you need one, say so at scoping and it is priced as its own thing.

Who maintains the plugin afterwards?

That is decided at scoping, and all three answers are workable — we can support it, your team can take it, or it can be handed to another developer. What makes the third possible is documentation and standards rather than goodwill, so both are part of the deliverable. A plugin that only its author can safely change is a plugin that constrains the site for as long as it exists.

What happens when WordPress is updated?

The plugin declares the WordPress and PHP versions it supports and is tested across those ranges, and the behaviours that would fail silently are the ones covered. Nothing guarantees a plugin across an unbounded future, which is why the update strategy is designed rather than assumed: what is tested, what version ranges are declared, and what the site does if the plugin is not updated alongside everything else.

Can you extend a plugin we already have?

Often yes, and the first step is reading it. A plugin written to standards and documented is straightforward to extend; one that is neither is a decision about how much can safely be changed and how much is better rebuilt. That assessment is the first deliverable, and it is occasionally the answer that the plugin is fine and needs nothing — which we will say rather than proposing a rebuild to have something to build.

How do you decide between custom tables and custom post types?

By how the data is used. Custom post types and taxonomies are right when editors manage the records as content and the volume is modest, because the administrative interface and the querying come with them. Custom tables are right where volume is high, where the access patterns are specific, or where the records are not editorially meaningful. Post meta suits values attached to existing content. The choice is made with the access patterns known, because it is the decision in a plugin that is hardest to revisit later.

Bring us the problem you have not been able to fix

Describe what is happening rather than what you think the cause is. If we are not the right people for it, we will say so.