Skip to main content
UTB Product Builder (v3.0.x) follows a Data-Driven UI / Dynamic Rendering pattern. Rather than hardcoding HTML forms and conditional logic, the plugin reads a JSON configuration array stored in WooCommerce product meta or in custom database tables, then assembles the UI at runtime. When a visitor lands on a CEP Program or Academic Certificate product page, the system launches FlowRegistry, delegates rendering to the matched AbstractFlow subclass, and that class paints the interface by recursively walking the JSON structure.

System diagram

Render pipeline

The following sequence describes what happens from the moment a user visits a product page to the moment a compiled form appears in the browser.

Core components

FlowRegistry

Central static registry that maps WooCommerce products to their assigned flow. Loads product→flow assignments from wp_utb_form_configs on first access and caches them in memory for the request lifecycle.

AbstractFlow

Base class for all flows. Registers WooCommerce hooks (woocommerce_add_cart_item_data, woocommerce_checkout_create_order_line_item, etc.), handles cart validation, dynamic pricing, and order meta persistence. Concrete flows extend this class.

FormConfigManager

Resolves form configuration for a given product and flow. Checks product post meta (_utb_form_config) first, then falls back to a linked certificate record, and finally to the flow’s built-in default config.

ApiConnectionManager

Generic, connection-agnostic HTTP hub. Given a $connection_id, it reads encrypted credentials from the database, negotiates OAuth2 tokens (cached as WordPress Transients), and injects Authorization headers into outbound requests.

RulesEngine

Programmable validation pipeline configured from the WordPress dashboard. At form submit time it interpolates field values into API endpoint URLs, calls ApiConnectionManager for auth headers, fires cURL requests, and evaluates JSON path mappings to accept or reject submissions.

DataSourceManager

Abstraction layer for dynamic <select> options. Reads data source definitions from wp_utb_data_sources and serves filtered option lists to the form renderer — no hardcoded data arrays in template code.

SubmissionHandler

Universal form data capture and persistence layer. Stores form submissions and uploaded files at cart time (temporarily), moves them to permanent storage on payment, and updates status on failure or cancellation. Works with every flow automatically.

Technology stack

LayerTechnology
BackendPHP 8.1+ with strict typing, abstract classes, and interfaces
DatabaseCustom tables via $wpdb; independent of wp_postmeta
FrontendPlain HTML5, CSS Flexbox/Grid, jQuery (WooCommerce compatibility only)
E-commerceNative WooCommerce hooks: woocommerce_add_cart_item_data, woocommerce_checkout_create_order_line_item
REST APINative WP REST API at /wp-json/utb/v1/ with custom Bearer Token validators
External commswp_remote_request wrapper over cURL for Banner/Iceberg integration
Token cachingWordPress Transients API
Auth typesOAuth2 Client Credentials, Bearer Token, HTTP Basic Auth

Key design decisions

No React or Vue. The frontend uses zero JavaScript framework dependencies. This avoids bundle fatigue and keeps the plugin compatible with any WordPress theme without build tooling. Custom DB tables, not wp_postmeta. High-volume form configuration and submission data is stored in dedicated tables (wp_utb_form_configs, wp_utb_product_submissions, etc.) to avoid the performance pitfalls of the key-value wp_postmeta table. Generic connection manager instead of per-API classes. ApiConnectionManager replaces what would have been separate CEPOAuthManager, BannerManager, and similar classes. New API integrations are added through the admin UI — no code changes required. Declarative logic binding. Field visibility, required state, and value propagation are expressed as a logic_binding JSON object attached to each field definition. The generic frontend script (form-builder.js) reads these declarations and wires up event listeners dynamically, so no custom JavaScript is needed per form. Flow extension point. The do_action('utb_pb_register_flows') hook, fired during Plugin::register_flows(), allows external plugins or themes to register additional flows into the registry without modifying the plugin’s own code.

Build docs developers (and LLMs) love