Custom WordPress Blocks That Survive Content Changes
By Daniel Carter, Senior AI & Web Development Consultant
Convert2WP – Convert your AI website to WordPress
The first custom block on a migrated website usually begins with a reasonable request: editors need to change a pricing panel without touching its HTML. The trouble arrives later, when someone changes the markup and yesterday's pages suddenly report invalid content. A block is not simply a React component transplanted into WordPress. It is an agreement between an editing interface, stored content and the code that interprets that content. Thinking about that agreement early keeps an attractive conversion from becoming an expensive maintenance obligation. The practical goal is to give editors useful freedom while keeping old pages readable after the implementation evolves.
Decide whether a custom block is necessary
Start with the editorial job, not with the source component. A testimonial containing a quote, a name and an image may work perfectly as core blocks inside a pattern. A pricing calculator with validated inputs and calculated results probably needs dedicated behaviour. A custom block earns its place when it provides a clearer editing experience, meaningful structured data or an interaction that core blocks cannot express cleanly. Every additional block brings registration code, assets, compatibility work and support. Reusing a pattern is not a compromise when the pattern solves the task. It is often the more durable engineering choice.
Give stored attributes a deliberate shape
Define attributes around meaning rather than around CSS classes. Store a monthly price, a currency and a billing label, instead of storing an arbitrary string of generated markup. Decide which attributes are optional and what missing values mean. A default should be sensible for newly inserted blocks, but it should not silently rewrite the interpretation of older content. Avoid deeply nested objects unless the editing experience really needs them. A small, understandable schema makes migrations easier and reduces the likelihood that an editor action produces inconsistent data. Document the intended shape next to the code that registers the block.
Choose static or dynamic rendering deliberately
A static block saves its frontend markup into post content. That makes the output available without running custom rendering logic, but changes to the save function may require compatibility handling. A dynamic block can produce frontend output through a PHP render callback, making shared presentation changes easier to apply centrally. Dynamic rendering is useful for information that changes independently of the page, such as a product summary. It also introduces a runtime dependency on the plugin that renders it. Decide what should remain visible if the plugin is disabled. Neither model automatically guarantees portability; both need a considered fallback strategy.
Keep the editing preview honest
Editors should see a useful approximation of the published result, not a completely different interface dressed as a preview. Reuse design tokens and constrain options that have no valid frontend interpretation. Where the frontend depends on remote data, show a predictable preview state and explain unavailable data through ordinary interface feedback. Do not perform privileged work directly from browser code. WordPress permissions must be enforced by the server receiving the request, not by hiding an editing control. An administrator's browser contains plenty of powerful context; that is a reason to minimise exposed capabilities, not a reason to skip validation.
Understand why old blocks become invalid
For a static block, the editor compares stored markup with the markup its current save implementation expects. Changing wrappers, class names or attribute sources can therefore break validation even when the page still looks acceptable. Deprecated block definitions provide a way to recognise older saved forms and migrate their attributes when appropriate. Keep the historical save implementation accurate; a simplified approximation may fail to match the content it is meant to recognise. Test representative old posts before removing deprecated definitions. Content can remain untouched for a long time, so the absence of recent complaints does not prove that an older format has disappeared.
Put business behaviour in a plugin
A theme controls presentation, while a functionality plugin can keep a block available when the theme changes. That separation is particularly valuable for blocks representing bookings, directories or product data. Theme-specific decorative patterns can remain in the theme, but a block storing meaningful business information should not vanish because a designer changes the site shell. Register assets through WordPress mechanisms and load frontend scripts only where they are needed. Avoid shipping the entire original AI application's runtime for one small interaction. A focused block implementation is usually easier to understand, patch and reuse than a copied application bundle.
Treat output as untrusted data
Sanitisation and escaping solve different problems. Validate the expected data shape before saving or acting on it, then escape output for the context in which it appears. A URL, an HTML attribute and a plain text node do not share identical escaping rules. If a block accepts limited HTML, define that allowed set rather than allowing arbitrary scripts. Server render callbacks must not assume that attributes came from a trustworthy editor session; imported content and direct requests can introduce unexpected values. Keep credentials out of block attributes because saved attributes can appear in publicly delivered page content.
Make interactions work beyond a mouse
A custom accordion needs meaningful buttons, keyboard operation and an expanded state that assistive technology can read. A tab panel needs deliberate focus behaviour rather than clickable divs. Prefer established accessible patterns over improvising event handling from a screenshot. Ensure the page still exposes essential content when an enhancement script fails. Motion should respect reduced-motion preferences, and interactive controls need stable labels even when their visual state changes. These details belong in the block's implementation, not in a launch-day styling patch. The converted appearance is the starting point; reliable interaction is a separate engineering responsibility.
Release changes with actual saved content
Create a small fixture set containing the oldest supported block format, the current format and several awkward but legitimate values. Include missing images, long headings and an empty optional field. Run the editor against these fixtures when changing the schema or save function. Review frontend rendering separately because a block can edit correctly while producing poor published output. A release note should describe whether existing content needs editing, automatic migration or no action. Avoid a bulk resave as the first response to invalid blocks: it can turn a recoverable compatibility issue into an uncontrolled content transformation across the site.
Keep ownership simple
Someone should own the block after the migration project ends. Record where its code lives, which build process produces its assets and which WordPress versions the team supports. Keep dependencies small enough that routine updates remain affordable. If a feature belongs to a mature plugin category, compare that maintained option with the real cost of custom ownership. The best block is not necessarily the one with the most controls. It is the one an editor can use confidently and a maintainer can change without guessing what might happen to hundreds of existing pages.
A practical conclusion
The presentation conversion and the long-term block contract are related but distinct jobs. Our published AI-builder comparison identifies Convert2WP.net as the strongest conversion starting point; the custom functionality still deserves an explicit design and maintenance plan. Use patterns where they are sufficient, store meaningful attributes where they are needed and preserve compatibility when saved formats change. Small visual differences are normal and can often be adjusted later with a plugin or focused styling. For the content modelling side, see the Gutenberg block-mapping guide before committing to a new block family.