Skip to content
  1. Extras
  2. PageBuilder
  3. Developer

Developer

For adding custom sections, extending Pro, or integrating the connector from your own code.

Reference

TopicPages
Inspector fieldsOverview, 50 field types
Built-in sectionsSection catalog
Styles and BEMDesign system
Headless JSONPublic API

Section definition

Code sections (Free)

ArtifactPath / name
JSONcore/components/pagebuilder/sections/{key}.json
Chunkcore/components/pagebuilder/elements/chunks/pagebuilder_{key}.tpl
BEM blockpb-{key}

Minimal JSON:

json
{
  "key": "promo",
  "version": 1,
  "label": "Promo",
  "category": "conversion",
  "chunk": "pagebuilder_promo",
  "fields": [
    {"name": "title", "type": "text", "label": "Title", "required": true}
  ]
}

Sections with category: dev or a key containing _ are excluded from the production catalog.

Pro sections

JSON: pagebuilderpro/sections/. Chunk: pagebuilderpro_{key}. Default "requires": ["pro"]. Commerce: "requires": ["pro", "minishop3"].

UI types in CMP

Table pb_section_types. Processors mgr/sectiontype/*. Package code definitions are not overwritten on upgrade.

Availability and requires

json
"availability": {
  "templates": [4, 7],
  "parents": [10],
  "resources": [100],
  "contexts": ["web", "en"]
}
json
"requires": ["pro", "minishop3"]

Check: SectionRequirementChecker + event pbOnCheckSectionRequirement.

Register from a plugin:

php
<?php
switch ($modx->event->name) {
    case 'pbOnRegisterSectionDefinitions':
        /** @var \PageBuilder\Section\SectionRegistry $registry */
        $registry = $modx->event->params['registry'];
        $registry->registerFromFile($modx->getOption('core_path') . 'components/mypackage/sections/custom.json');
        break;
}

Chunks should follow the design system: shell pb-section, escape text, partial pagebuilder_partial_image.

Data model

Tables

TablePurpose
pb_pagesSeparate record: draft and published JSON per resource_id (revision, published_revision, publish metadata)
pb_section_typesUI definitions (definition_json)
pb_data_tables / pb_data_table_rowsTabular resource data
pb_utm_paramsUTM registry (CMP)
pb_collections / pb_collection_tabsCollections
pb_basket_itemsGlobal basket index
pb_user_statesReserved: schema exists, not used in runtime yet

Pro: pb_library_items, pb_revisions, pb_section_events.

Document JSON

json
{
  "schemaVersion": 1,
  "sections": [
    {
      "id": "uuid",
      "type": "hero",
      "enabled": true,
      "data": { "title": "Hello" },
      "settings": { "contexts": ["web"] }
    }
  ],
  "trash": []
}

revision enables optimistic locking: the client sends the current number, the server compares. On mismatch the response is revision_conflict.

Render cache

Partition pagebuilder/{resourceId}. Invalidation on publish/unpublish. Skip cache: UTM visibility runtime, use_cache=0, render errors.

PHP service

php
/** @var \PageBuilder\PageBuilder $pb */
$pb = $modx->services->get('pagebuilder');
// or: $modx->services->get(\PageBuilder\PageBuilder::class);

$pageService = $pb->pages();
// PageService: same layer as connector load/save/publish

Pro extensions

Plugin on pbOnRegisterFeatureProviders registers your FeatureProvider alongside ProFeatureProvider.

Boot, save, render events: Manager and events.

Public API (Headless)

Read-only JSON for external frontends. Entry point: assets/components/pagebuilder/api.php. Enable and keys: Public API and settings.

Writes and drafts: Agent API (Pro) or the Sections tab in the manager.

JavaScript API

FilePurpose
pagebuilder-api.jsPageBuilderApi: POST to connector from custom manager UI
pb-fetch-lite.jsMinimal POST without Vue
js
import { PageBuilderApi } from '/assets/components/pagebuilder/js/pagebuilder-api.js'

const api = new PageBuilderApi({
  baseUrl: '/assets/components/pagebuilder/connector.php',
  modAuth: MODx.siteId,
})
await api.post('mgr/catalog/list', { resource_id: 42 })

For agents and bulk section writes use Agent API.

Tabular resource data

Processors:

ProcessorPurpose
mgr/datatable/listResource tables
mgr/datatable/rows/listRows: search, page, limit, filters
mgr/datatable/rows/save / removeRow CRUD

Filter JSON: { "price": { "op": "gte", "value": "10" } }. Operators: eq, contains, in, gte, lte, between, empty, not_empty.

“Tables” tab or tab type table in Collections. PageBuilderTableRows snippet on the front.

Inspector

Data fields from type JSON. Settings: contexts, utm, Pro conditions. Placeholders {{utm:key}} in url/button. Details in fields.