Custom MODX plugin development: from event to production

Manual operations, catalog mismatches with external systems, and a queue of edits for the developer — a familiar picture for a website on the platform. We develop custom MODX plugins turnkey: from the event scheme to deployment and documentation. After implementation, typical processes run without manual involvement, and time spent on routine tasks is reduced several times over.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Frequently Asked Questions

Custom MODX plugin: where site logic breaks

A custom MODX plugin almost always starts with a single event — and quickly grows to a dozen. A plugin on document save recalculates prices, a neighboring one on the same event clears the cache, and a third sends data to an external system.

While each was written separately, everything works; after the first change to the connection order, the site starts saving pages without recalculation.

Handler conflict is the most common cause. The result depends on priority and load order: two plugins on the same event overwrite each other's output, and this is not visible in the log or the interface.

A few failed saves — and the catalog is left with zero-price items that no one will notice until the client's first complaint.

Data exchange errors look different: the external system's response arrives in parts, and the plugin writes to the database before checking integrity. A repeated scheduled run duplicates records, and the discrepancy quietly accumulates.

A separate class is silent errors in the admin panel, when an exception is swallowed, one line goes to the log, and the operator sees a cheerful “saved”.

Debugging custom logic starts with a reproducible scenario and an explicit hook order — then handler conflicts stop being accidental. Next, we break down how this is resolved: from the event map and change procedure to checks before deployment to production.

What changes after implementation: effect in numbers

A plugin subscribes to MODX core events — resource save, publication, order checkout — and triggers at the moment of the action, not on a manager's reminder.

This simultaneously changes the share of manual operations, the load on the admin panel, and system behavior during a failure.

Automation takes over repetitive actions: recalculating stock, filling related fields, generating page URLs, exporting to adjacent systems. Manual edits in a typical flow decrease by 80–90%, and where edit access used to be required, only result monitoring remains.

The admin panel is unloaded not so much by the number of operations as by their weight. Heavy queries and calls to external services go into deferred processing: the interface responds in the same time as before, while the task queue is processed in the background.

Unavailability of an adjacent system no longer blocks saving — the edit is recorded, and the retry starts automatically.

A separate effect is the eliminated class of failures during saving and synchronization. Previously, a discrepancy between the catalog and an adjacent system was found from a client complaint, and the reaction time to a failure was measured in hours.

Now the plugin verifies the result immediately after the event and writes the discrepancy to the log: reaction is reduced to minutes, and some failures are resolved without human involvement.

We measure the effect of implementation before and after on a real data flow — by the event log, not by the team's feelings. The metrics are verifiable on a staging environment, so the result does not have to be taken on faith.

Implementation options: plugin, snippet, core modification

MODX allows almost any customization to be done in several ways, and the choice here is not about “how to write it faster.” The event model provides intervention points in system processes, snippets cover output logic, and the core is formally open to modifications — but each branch leaves a different footprint on maintenance.

We start with the question of whether there is a suitable event or the task comes down to output in a template: the answer determines whether the customization will survive a platform update and what its maintenance will require a year from now.

Option When it fits Limitations
Event plugin You need to intervene in a system process: resource save, order status change, authorization Execution order is set by priority; an error in the handler crashes the entire request
Snippet Output or calculation in a specific template location, one-off logic without reaction to actions Does not trigger on events; the result is cached together with the page
Standard extra Reusable functionality: customer account area, reference data exchange, custom entities Requires an admin interface and its own table structure; higher entry threshold
Core modification A last resort when there is simply no suitable event to hook Updates overwrite changes; rollback is possible only from a backup
External service Logic lives outside the system: heavy calculations, exchange with an accounting environment Requires a separate reliability layer — wait time, retries, conflict resolution

Core modification and an external service are the extreme points. The first requires less effort at the start, but every update turns into a manual merge; the second moves reliability outside the application.

An event plugin and a standard extra more often provide a workable balance: the code lives separately from the core, updates normally, and can be moved between projects.

Development stages: from event schema to rollout

A plugin in MODX is a subscription to core events: the code triggers when the system saves a document, builds a page, or changes settings. The plugin development stages follow one rule — first understand the intervention points, then write code.

That is why the work starts with an audit: you need to understand which handlers are already attached to the required events and in what order they execute; otherwise, the new plugin will override logic that has worked for years.

  1. Site audit — inventory of intervention points: active plugins, snippets, context settings, templates. The output is a map: what we reuse, what we override, what must not be touched.
  2. Event and data schema — list of events, handler priorities, affected tables and fields, behavior during partial failure. Agreed before the first line of code.
  3. Prototype — a minimal plugin with one handler on a test copy: we check that the event occurs at the right moment, the data arrives complete, and the admin panel and public part do not degrade.
  4. Testing on a site copy — we deploy a copy with a comparable data volume and run scenarios: publication, editing, deletion, access rights, batch operations.
  5. Failure testing — external service unavailability, repeated event call, bulk import. The plugin must not block document saving.
  6. Rollout to the production site — step by step: backup, cache and compiled template reset, plugin enablement, monitoring the error log for the first day.
  7. Handover — repository, description of events and settings, instructions for rollback to the previous version.

Delivery package: code, schemas, procedures, documentation

A plugin lives longer than any contractor: a year from now, someone on your team will need to open the code, understand which events it subscribes to, and safely make a change.

That is why we fix the delivery package before work begins — not as a formality, but as a way to remove dependence on us.

  • Code handover — repository with full history, access is registered to the customer, deployment on a clean environment is reproduced according to instructions.
  • Event and dependency schema — which MODX events the plugin intercepts, in what order handlers trigger, and what changes if any of them are disabled.
  • Plugin documentation — purpose, settings, extension points, known limitations; readable without needing to contact us.
  • Update procedure — the order of work when updating the core or neighboring plugins: what we check, in which environment, and how we return to the previous version.
  • Change log — what changed and why in each release, and which edits affected behavior in the production environment.
  • Team instructions — enabling and disabling the plugin, where to view logs, what to do during typical failures.
  • Set of checks — a set of tests and an acceptance checklist by which the receiving party independently confirms operability after an update.

Handover is a walkthrough, not an archive: we go through each artifact together with your engineers, answer questions, and record the remaining risks. Describe the task — we will return with an estimate and a plan.

Case: catalog synchronization with an external system

What was before implementation

The client's catalog has 12,400 items, and the supplier's price list arrived as a file twice a day. A manager transferred it manually: a full reconciliation took 3-4 hours, and items that were not in the new export remained from the previous run.

Prices on the site lagged by up to 20 hours, and stock levels diverged — according to internal measurements, 6-7% of products were shown as available when the warehouse was empty.

Every week this led to one or two cancellations of already paid orders and a dispute with the client.

What was changed and what the result was

A plugin on MODX subscribes to item save events and catalog requests: edits go to the external system as a queue, and the response is applied to catalog resources without human involvement.

The exchange runs in batches of 500 records, with retry on failure, an operations log, and a separate discrepancy report — instead of silently skipping items. The platform core is not affected, so updates proceed normally and do not break the integration.

The before and after metrics differed noticeably: a full catalog pass takes 40 seconds, the exchange runs every 15 minutes, and it transfers only changes.

The share of manual operations fell from 100% to zero, stock discrepancies are below 0.5%, and the price on the site updates within ten minutes after a supplier edit.

Cancellations due to “out of stock” stopped, and the exchange log answers what changed and when: in a disputed situation, the data source and recording time are visible.

How does an event handler differ from a template call?

An event handler is a plugin that subscribes to a system event and is called by the core itself at the moment the event occurs.

A template call is a snippet inserted in a specific place in a template or chunk: the logic executes where the front-end developer placed it, and only on pages where that template is applied.

Hence the main difference in reliability.

The handler lives at the data model level: whether a resource was saved from the control panel, a batch was uploaded via import, or a value was corrected by a script — the reaction will work the same, because there is one intervention point for all routes.

A template call covers only the path where it is written: if the template is changed or data is provided in another way, the logic will silently fail to run, and the discrepancy will be discovered on production data.

The execution order in the event schema is controlled by handler priority. Several plugins on the same event line up in a chain, and you can guarantee that validation and normalization run before saving, not after.

In a template, the order is set by the markup: it depends on output order and breaks with the first change to the layout.

The handler also wins on speed. Logic in a template executes on every page build, that is, for every visitor, and directly affects response time. Work on an event happens once — at the moment of change, while delivery only reads already prepared data. Heavy operations are moved to deferred tasks so the editor does not wait for saving to complete.

That is why intervention points are chosen by the question “where does the data change,” not “where is it convenient to output it.” A template call remains for presentation tasks — output a prepared value, assemble a block from the cache.

Technical doubts: what we clarify before start

Before the start, we synchronize expectations with the customer's technical team — at this stage, most maintenance risks are removed. Below are the questions we ask and the ones most often asked of us.

Will the plugin survive a CMS update?

We package core event subscriptions as a separate package and do not modify the core — an update does not overwrite the logic. Before release, we run scenarios on the current branch and on LTS: changes in handler call order do not surface on the live site.

Who is responsible for supporting custom code?

We transfer the source code to your repository and describe events, handlers, and extension points. After that, support is handled by your team according to the documentation or by us — under the version release procedure.

What access is needed at the start?

A test environment, a database copy, access to the admin panel, file structure, and logs. We reproduce everything on the copy: if a scenario breaks, the live site remains untouched.

How is the plugin logic tested?

We cover handlers with checks for events and edge-case data: empty values, duplicates, unavailability of external services. We run regression against the list of affected events so the new logic does not break neighboring scenarios.

Will you take on refining someone else's plugin?

First an audit: we record dependencies on the CMS version and third-party extras, then make changes while preserving current behavior. We rewrite risky parts gradually, not with a single change.

Let's discuss the task: what to clarify before estimation

For the estimate to be based on facts rather than assumptions, we need inputs about the system and the expected plugin behavior. They determine the scope of work and the plan — with the same description “we need a plugin,” the scope can differ by several times.

  • Extension points: which events the plugin subscribes to, in what order they trigger relative to standard logic, and what happens when an operation is rolled back.
  • Expected behavior: what exactly the plugin changes in output or data, which scenarios are considered correct, and which are errors.
  • Project state: the current MODX branch, the set of snippets, chunks, templates, and already installed extras — so as not to conflict with existing logic.
  • Integrations: external services, exchange directions, data formats, and call frequency.
  • Load: content volume, number of simultaneous operations, where caching and deferred processing are needed.
  • Access: test environment, repository, permissions to deploy and to read configurations.
  • Acceptance criteria: which checks must pass on the test environment before transfer to production.

We begin the task discussion by reviewing these inputs together with the engineer who will lead development: we clarify disputed points, note migration risks, and only after that return with an estimate and a stage-by-stage work plan.

Our competencies:

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1393
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1368
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1139
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1152
  • Website development for SBH Partners
    Website development for SBH Partners
    1231
  • Website development for Red Pear
    Website development for Red Pear
    641