Add a New Appearance to the Product Content-Type for the Page Builder on Magento 2 EE

The recent addition of Page Builder (formely known as BlueFoot when it was available as a separate extension), allows for a more user-friendly way to create CMS Pages. However, when using a Products item to generate a list of products, only one template is available. Let me show you how to create new templates and make them available on the creation form.

Short Explanation (+ Download)

Behind the scene, a Products item from the PageBuilder is just a wrapper for the ProductsList widget. Therefore, the process is fairly simple, we just need to:

  1. Tweak some JavaScript (widget-directive.js) to allow new templates to be used.
  2. Create a valid .phtml file using the methods available for ProductsList widget (Magento\CatalogWidget\Block\Product\ProductsList).
  3. Add a new Appearance with some XML.

Download the module from this article

You can download an archive of the module here. Just drop it at the root of your website and modify what you need based on the tutorial below.

Full explanation

Create a module

First thing we have to do is create a new module. Here's a link to the official documentation if you don't know how to do it.

For the example, we'll name the module Thedotwriter_PageBuilderExtensionProducts (following the naming convention used in the documentation for extending a content type).

List of files

Here's a tree view of all files and folders we're going to create:

            │   composer.json
            │   registration.php
            │   │   module.xml
            │   │   
            │   └───adminhtml
            │           di.xml
                │   ├───pagebuilder
                │   │   └───content_type
                │   │           products.xml
                │   │           
                │   └───web
                │       ├───css
                │       │   └───images
                │       │       └───content-type
                │       │           └───products
                │       │               └───appearance
                │       │                       menu-list-complex.svg
                │       │                       menu-list-simple.svg
                │       │                       
                │       └───js
                │           └───content-type
                │               └───products
                │                   └───mass-converter
                │                           widget-directive.js

Now, let's explain them one by one.

Add a dependency to Magento_PageBuilder

Let's make sure to load our module components after Magento_PageBuilder. For that, add a <sequence> to your module.xml file:


<?xml version="1.0"?>
<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Thedotwriter_PageBuilderExtensionProducts" setup_version="0.1.0">
            <module name="Magento_PageBuilder"/>

Create a new widget convertor

Remember, the Products PageBuilder item is only a wrapper for the already existing ProductsList widget ("Catalog Product List" in the backend). Therefore, the PageBuilder item configuraton needs to be passed to a ProductsList widget at some point. That's the job of the widget-directive.js convertor.

There's one issue with it though, the path to the phtml file is hard coded into the original file. So, we're gonna create another JS convertor that lets us set the phtml file as a setting in the products.xml file. It's quite simple (once you spent enough time looking around!):

Into our module :

Then in the toDom() function, change the line 53:

template: "Magento_CatalogWidget::product/widget/content/grid.phtml",

Into this:

template: config.template_path,

Create a new template file

Now, create an empty .phtml file in the following path in our module:

This example being based on a recent work of mine, the file is called widget-menu-list-simple.phtml, but call it however you want. Just remember to update the name in the products.xml file I'll make you create later. That's where the template file will be specified.

In the ZIP file provided in this article, you'll find an example of how to work with this template. But if you want more, you can check out the original grid.phtml file in vendor/magento/module-catalog-widget/view/frontend/templates/product/widget/content/.

Add a new Appearance

To setup a new Appearance, start by creating a products.xml file in
view/adminhtml/pagebuilder/content_type/. Then add the following:

<?xml version="1.0"?>
<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_PageBuilder:etc/content_type.xsd">
    <type name="products">
            <appearance name="menu-list-simple"
                    <element name="main">
                        <style name="text_align" source="text_align"/>
                        <style converter="Magento_PageBuilder/js/converter/style/border-style" name="border" source="border_style"/>
                        <style converter="Magento_PageBuilder/js/converter/style/color" name="border_color" source="border_color"/>
                        <style converter="Magento_PageBuilder/js/converter/style/border-width" name="border_width" source="border_width"/>
                        <style converter="Magento_PageBuilder/js/converter/style/remove-px" name="border_radius" source="border_radius"/>
                        <style name="display" source="display" converter="Magento_PageBuilder/js/converter/style/display" preview_converter="Magento_PageBuilder/js/converter/style/preview/display"/>
                        <style name="margins" storage_key="margins_and_padding" reader="Magento_PageBuilder/js/property/margins" converter="Magento_PageBuilder/js/converter/style/margins"/>
                        <style name="padding" storage_key="margins_and_padding" reader="Magento_PageBuilder/js/property/paddings" converter="Magento_PageBuilder/js/converter/style/paddings"/>
                        <attribute source="data-content-type" name="name"/>
                        <attribute source="data-appearance" name="appearance"/>
                        <html name="html" preview_converter="Magento_PageBuilder/js/converter/attribute/preview/store-id"/>
                        <css name="css_classes"/>
                    <converter component="Thedotwriter_PageBuilderExtensionProducts/js/content-type/products/mass-converter/widget-directive" name="widget_directive">
                            <item name="html_variable" value="html"/>
                            <item name="template_path" value="Thedotwriter_PageBuilderExtensionProducts::product/widget/content/widget-menu-list-simple.phtml"/>

What we've done above is copy the default "grid" <appearance> (originally set in vendor/magento/module-page-builder/view/adminhtml/pagebuilder/content_type/products.xml), put it in our XML file and change the name of the appearance to menu-list-simple.

Next, we update the path of the widget_directive converter to Thedotwriter_PageBuilderExtensionProducts/js/content-type/products/mass-converter/widget-directive which will make Magento use our javascript file created earlier:

<converter component="Thedotwriter_PageBuilderExtensionProducts/js/content-type/products/mass-converter/widget-directive" name="widget_directive">

And finally, we add a new config item named "template_path" to the converter settings. That's where you specify the template you want to use:

<item name="template_path" value="Thedotwriter_PageBuilderExtensionProducts::product/widget/content/widget-menu-list-simple.phtml"/>

Make the new Appearance available in the backend

Once the Appearance is created, you have to tell Magento to make it available for the PageBuilder Products item.

This is done by adding this to your module di.xml file:

<?xml version="1.0"?>
<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <virtualType name="AppearanceSourceProducts">
            <argument name="optionsData">
                <item name="1" xsi:type="array">
                    <item name="value" xsi:type="string">menu-list-simple</item>
                    <item name="title" xsi:type="string" translate="true">Menu List Simple</item>
                    <item name="icon" xsi:type="string">Thedotwriter_PageBuilderExtensionProducts/css/images/content-type/products/appearance/menu-list-simple.svg</item>

Update the value, title and icon of the item according to the appearance name, the label you want to show on the edit form and the SVG icon you want to use.

Don't forget to enable your module and clear the cache and you should be good to go!