Page Builder was introduced with Magento Commerce 2.3.1. It’s the successor of “Bluefoot“, an advanced, intuitive and very flexible CMS tool for individual layouts and content elements.
A typical task for a developer is to create a new content element with a few custom fields. In the end, it should output a given HTML snippet, including information from the custom fields. This little tutorial will show you how to create a simple content element.

How Page Builder works

The basic principles of Page Builder are different from those of Bluefoot or the default Magento CMS. Page Builder uses JavaScript and UI components heavily. It consists of the following parts:

  • A backend form, defined by UI components (XML)
  • A frontend output template, called master template (HTML)
  • An XML configuration file including a mapping between input fields (in the backend form) and output fields (in the master template)
  • A JavaScript engine which fills the master template with the correct field values and saves the generated HTML in the database

Example: Hero Teaser

We use a simplified example for showing the general principles. We want to display a so-called “hero teaser” – an image with a headline and a “call to action” link.

The Directory Structure

Page Builder Directory Structure

I recommend having one Magento module per Page Builder element. In this case, it’s named “PageBuilderHeroTeaser” and can either be in app/code/<namespace>/ or included via composer. While there is nothing special in the module base-files (“composer.json”, “registration.php”, “etc/module.xml”), you can see that all Page Builder specific files are in the “view” directory.
These files serve the following purposes:

  • view/adminhtml/layout/pagebuilder_hero_teaser_form.xml: A few lines to include the backend form into the Page Builder. Nothing more than copy & paste.
  • view/adminhtml/pagebuilder/content_type/hero_teaser.xml: The main configuration file for the element
  • view/adminhtml/ui_component/pagebuilder_hero_teaser_form.xml: The backend form definition
  • view/adminhtml/web/template/content-type/hero-teaser/default/master.html: The master template which is used for rendering of the frontend
  • view/adminhtml/web/template/content-type/hero-teaser/default/preview.html: Similar to the master.html, but for the backend view (“Preview”)

The Page Builder reads all files in the “view/adminhtml/pagebuilder/content_type” directory of each module. In our example, the main configuration file “view/adminhtml/pagebuilder/content_type/hero_teaser.xml” contains the following line:

With this information, the Page Builder knows to load the “pagebuilder_hero_teaser_form.xml” file from the “view/adminhtml/layout” directory.

The Files

view/adminhtml/layout/pagebuilder_hero_teaser_form.xml

This file includes the new backend form into the Page Builder areas. Please note that the name (here: “pagebuilder_hero_teaser_form”) is the name of the UI component file.

view/adminhtml/ui_component/pagebuilder_hero_teaser_form.xml

This file contains the backend form definition. Please note the marked lines especially, as they define the three fields we want to have: headline, link_url, and link_text. In this case, they are all text fields. For more field types please see the existing page elements delivered with the Page Builder module.

The form then looks like this:

Page Builder Backend Form

view/adminhtml/pagebuilder/content_type/hero_teaser.xml

This file contains the general page element configuration. At the top, you see the identifier (“name”), label, icon and sort order as well as the components used for rendering frontend (“master”) and backend (“preview”) output. We use the default components here: “Magento_PageBuilder/js/content-type/master” and “Magento_PageBuilder/js/content-type/preview”.
In the appearance section (you can have several appearances which are different layouts for the element), you find links to the preview_template and master_template. In the “elements” definition below, you can see a mapping between the admin form fields (names “attributes”) and the template fields (“elements”).

view/adminhtml/web/template/content-type/hero-teaser/default/master.html

This file is used for rendering the form input into HTML and saving the result in the database. Now the element definition from the configuration file “hero_teaser.xml” comes into play. The template contains placeholders which look like “data.<element_name>.<attribute_name>” while the element names and attribute names are defined in the configuration file “hero_teaser.xml”. There is also a general attribute name “attributes” which contains all attributes of an element.

Into the database

Upon saving the CMS page / CMS block / product / …, the HTML will be rendered by JavaScript and saved in the database directly. This can look as follows:

Page Builder Saved Data

Dynamic Content

A typical purpose of Page Builder elements is showing dynamic content which depends on the database. You can’t do that directly with just HTML. If you want to do that, you can insert a widget. Here is what it can look like in the master.html:

Exactly this mechanism is used for displaying product lists in the core Page Builder elements. You replicate the input via the UI component and pass them through to the widget.

Advanced Features

There are many more features which are not covered in this blog post:

  • Images
  • Other input types like selects
  • Modifying the input with JavaScript
  • Nesting different elements (i.e. for Sliders)

There are many examples in the core elements which you can copy.
Also, check out the official Developer Documentation which is the most complete documentation you will find.

Migration from Bluefoot to Page Builder

There is an official migration tool which will transform all default Bluefoot content elements to Page Builder. Please see the official developer documentation for its usage. The documentation also describes how to migrate custom content types.
Make sure to have this one condition fulfilled if you want to use the migration tool:

  • The migration tool can only be used in Magento Commerce 2.3.1. It won’t work in 2.3.2 or newer.

This means that you have to migrate from Magento 2.2.x to 2.3.1 first, then migrate the content, and then update to Magento 2.3.3 or newer. Please plan accordingly.

Andreas von Studnitz

Author: Andreas von Studnitz

Andreas von Studnitz is a Magento developer and one of the Managing Directors at integer_net. His main areas of interest are backend development, Magento consulting and giving developer trainings. He is a Magento 2 Certified Developer Plus and a Magento (1 and 2) Certified Solution Specialist. He was appointed a Magento Master in 2019.

More Information · Twitter · GitHub · LinkedIn