How to Create Your Own Custom Addon in SP Page Builder 4 - JoomShaper

How to Create Your Own Custom Addon in SP Page Builder 4

17 October 2022
Hits 716
16 min read
How to Create Your Own Custom Addon in SP Page Builder 4

Did you know that you can create your own SP Page Builder custom addon? SP Page Builder already has a vast collection of addons that are well-built, user-friendly, and makes your Joomla website completely functional. But knowing how to fine-tune your custom addon based on your needs will make you unstoppable.

The idea of creating your own addon may seem overwhelming especially if you’re not a professional developer, but it is actually doable! Turns out, you’ll only need to know the basics of coding to turn your desired functions into an addon.

First Things First

Before you start, we highly recommend using a local web development environment first. This will give you the freedom to learn and test things out without the worry of messing up your live site.

If you’re new to SP Page Builder, here’s our detailed guide on how to download and install SP Page Builder. Alright now that we have the disclaimer out of the way, let’s get into the tutorial.

Step 1: Create a Custom Plugin

First, we’ll create a custom plugin and then add our custom addon code there. But wait, weren’t we supposed to create a custom addon? Yes, that mission is still live!

With a plugin, you can install one or multiple addons. Ideally, creating a plugin to install your custom addons lets you add your custom addons that aren’t dependent on the SP Page Builder core component. This means once you update your SP Page Builder you’re not going to lose your custom addons.

To create a custom plugin, you need to first create a folder and name it plg_sppagebuilder_demo. Here, demo is the name of the plugin. You can replace ‘demo’ with your preferred plugin name if you want.

Inside the plg_sppagebuilder_demo folder, we’ll need to create the followings:

  • A PHP file named: demo.php
  • An XML file named: demo.xml
  • A folder named: addons

Step 2: Create the demo.php File Inside the Custom Plugin

Let’s start by creating the PHP file of the plugin. To do that, we’ll need a text/code editor. You can use any text/code editor you prefer. For this tutorial, we’re using Sublime Text because it has a free version and is extremely lightweight.

Open the folder that we have just created from the editor and create a file named demo.php. Please note, our plugin name is Demo, hence the name of the file is demo.php. If you’re using any other name, the name of the file should be yourPluginName.php.

Now, paste the following code snippet.

<?php
/**
* @package SP Page Builder
* @author JoomShaper http://www.joomshaper.com
* @copyright Copyright (c) 2010 - 2022 JoomShaper
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
*/

//no direct accees
defined('_JEXEC') or die('Restricted Access);
use Joomla\CMS\Plugin\CMSPlugin;
class PlgSppagebuilderDemo extends CMSPlugin {
	protected $autoloadLanguage = true;
}

Here, the Demo in Class name ‘PlgSppagebuilderDemo’ must be replaced with your plugin name.

Step 3: Create the demo.xml File Inside the Custom Plugin

Now, we'll need to create an XML file for our plugin. Create a new file on your code editor, name it demo.xml, and paste the following code snippet.

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.8" type="plugin" group="sppagebuilder" method="upgrade">
	<name>Demo Addon Plugin - SP Page Builder</name>
	<author>JoomShaper</author>
	<creationDate>22 Sep 2022</creationDate>
	<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.</authorEmail>
	<authorUrl>https://www.joomshaper.com</authorUrl>
	<copyright>Copyright (C) 2010 - 2022 JoomShaper. All rights reserved.</copyright>
	<license>GNU/GPL V2 or Later</license>
	<description>Demo addon plugin for SP Page Builder</description>
	<version>1.0</version>

	<files>
		<filename plugin="demo">demo.php</filename>
		<folder>addons</folder>
	</files>

</extension>

Here, you need to draw attention to the following lines of code:

  • In the <name> tag, you need to put the name of your plugin.
  • In the <description> tag, replace “demo” with the name of your plugin.
  • In the <filename> tag, replace the file name demo.php with your plugin PHP file.
  • In the <folder> tag, make sure to set the folder name to "addons". We’ll create the folder in the next step.

Step 4: Create the “addons” Folder

In this step, we’ll create a folder inside our plugin folder. From the code editor, create a new folder inside the custom plugin and name it addons. This is where we will store all our custom addons.

Inside the addons folder, create another folder and name it rich_text.

Note: In this tutorial, we will be using Rich Text as the name of our new custom addon.

Inside the rich_text folder, you need to create the following files: 

  • A PHP file named admin.php
  • A PHP file named site.php
  • A folder named assets to store all the assets for the addon

Here’s what the file structure will look like: 

Custom addon file structure

As we’ve mentioned earlier, you can install multiple addons using a plugin. So, if you wish to add another custom addon, simply create a folder with the name of that addon inside the addons folder.

Step 5: Write the Custom Addon Specific Functions

In this section, we’ll start writing code to add features to our Rich Text addon. Before jumping on to the code, let’s figure out what we want our Rich Text addon to do.

Ideally, the Rich Text web element lets you create long-form content. Instead of adding Heading, Paragraph, Button, Image, etc. individually, Rich Text lets you add these different content elements directly.

For this tutorial, we’ll keep our Rich Text really simple. It’ll have a heading, a paragraph, and a button as shown in the image below.

custom addon preview

Create the Addon Icon

First, let’s add the icon of our addon. In the assets folder, create a new folder and name it images. Inside the images folder, add your icon.png file. Here, we have kept the size of the icon 76 x 76 px. If you want to change the icon of your addon, you can just replace the icon image.

Create the admin.php File

Now, let’s create a new PHP file inside the rich_text folder and name it admin.php then paste the following code snippet.

<?php
/**
 * @package SP Page Builder
 * @author JoomShaper http:   //www.joomshaper.com
 * @copyright Copyright (c) 2010 - 2022 JoomShaper
 * @license http:   //www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
 */

// No direct access
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Language\Text;

/**
 * Inline editor settings rules:
 * 1. The inline array must have an attribute named `buttons`
 * 2. The buttons array contains all the editor buttons. The key of the array must be unique.
 * 3. Every button contains some attributes like-
 *         a. action (string) (required) [The action will perform after clicking the button]
 *         b. type (string) (required) [The type of the button. valid values are `placeholder`, `icon-text`]
 *         c. placeholder (string) (optional) [If the button is dynamic and this cannot be expressed as icon/text.]
 *         d. icon (string) (optional) [A valid icon name available in the pagebuilder]
 *         e. text (string) (optional) [A text value to show as the button text]
 *         f. icon_position (string) (optional) [`left` or `right` position of the icon to the text. Default `left`]
 *         g. tooltip (string) (optional) [Tooltip text to show on the button hover.]
 *         h. fieldset (array) (conditional) [An conditional array (which is required if action is dropdown) for representing the fieldset fields.
 *             This is valid only if the action is `dropdown`.
 *             The direct children of the fieldset array would be the tabs.
 *             Inside the tabs name you should define the fields descriptions.
 *             If there is only one fieldset child then that means no tabs]
 *         i. options (array) (conditional) [This is a conditional field. This is required if the action is dropdown
 *             but you need to show some options not fields.]
 *         j. default (mixed) (conditional) [This is required if there is the options key. This indicates the default value of the button from the options array.]
 */

SpAddonsConfig::addonConfig(
    [
        'type' => 'content',
        'addon_name' => 'rich_text',
        'title' => 'Rich Text',
        'desc' => 'Rich Text Custom addon',
        'category' => 'Custom',
        'icon' => '',
        'inline' => [
            'buttons' => [
                'rich_text_general_settings' => [
                    'action' => 'dropdown',
                    'icon' => 'addon::rich_text',
                    'tooltip' => 'Rich Text',
                    'fieldset' => [
                        'tab_groups' => [
                            'title' => [
                                'fields' => [
                                    [
                                        'title' => [
                                            'type' => 'text',
                                            'title' => Text::_('COM_SPPAGEBUILDER_ADDON_TITLE'),
                                            'desc' => Text::_('COM_SPPAGEBUILDER_ADDON_TITLE_DESC'),
                                            'std' => 'This is a advanced heading',
                                        ],
                                        'heading_selector' => [
                                            'type' => 'headings',
                                            'title' => Text::_('COM_SPPAGEBUILDER_ADDON_HEADINGS'),
                                            'std' => 'h3',
                                        ],
                                    ],
                                ],
                            ],
                            'content' => [
                                'fields' => [
                                    [
                                        'content' => [
                                            'type' => 'editor',
                                            'title' => Text::_('COM_SPPAGEBUILDER_ADDON_TITLE'),
                                            'desc' => Text::_('COM_SPPAGEBUILDER_ADDON_TITLE_DESC'),
                                            'std' => "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.",
                                        ],
                                    ],
                                ],
                            ],
                            'button' => [
                                'fields' => [
                                    [
                                        'button' => [
                                            'type' => 'text',
                                            'title' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_TEXT'),
                                            'desc' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_TEXT_DESC'),
                                            'std' => 'Button',
                                        ],
                                        'type' => [
                                            'type' => 'select',
                                            'title' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_STYLE'),
                                            'desc' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_STYLE_DESC'),
                                            'values' => [
                                                'default' => Text::_('COM_SPPAGEBUILDER_GLOBAL_DEFAULT'),
                                                'primary' => Text::_('COM_SPPAGEBUILDER_GLOBAL_PRIMARY'),
                                                'secondary' => Text::_('COM_SPPAGEBUILDER_GLOBAL_SECONDARY'),
                                                'success' => Text::_('COM_SPPAGEBUILDER_GLOBAL_SUCCESS'),
                                                'info' => Text::_('COM_SPPAGEBUILDER_GLOBAL_INFO'),
                                                'warning' => Text::_('COM_SPPAGEBUILDER_GLOBAL_WARNING'),
                                                'danger' => Text::_('COM_SPPAGEBUILDER_GLOBAL_DANGER'),
                                                'dark' => Text::_('COM_SPPAGEBUILDER_GLOBAL_DARK'),
                                                'link' => Text::_('COM_SPPAGEBUILDER_GLOBAL_LINK'),
                                            ],
                                            'std' => 'default',
                                        ],
                                        'url' => [
                                            'type' => 'link',
                                            'title' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_URL'),
                                            'mediaType' => 'attachment',
                                        ],
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
                'rich_text_alignment_separator' => [
                    'action' => 'separator',
                ],

                'rich_text_alignment_options' => [
                    'action' => 'dropdown',
                    'type' => 'placeholder',
                    'style' => 'inline',
                    'showCaret' => true,
                    'tooltip' => Text::_('COM_SPPAGEBUILDER_GLOBAL_ALIGNMENT'),
                    'placeholder' => [
                        'type' => 'list',
                        'options' => [
                            'left' => ['icon' => 'textAlignLeft'],
                            'center' => ['icon' => 'textAlignCenter'],
                            'right' => ['icon' => 'textAlignRight'],
                        ],
                        'display_field' => 'alignment',
                    ],
                    'default' => [
                        'xl' => 'center',
                    ],
                    'fieldset' => [
                        'basic' => [
                            'alignment' => [
                                'type' => 'alignment',
                                'inline' => true,
                                'responsive' => true,
                                'available_options' => ['left', 'center', 'right'],
                                'std' => [
                                    'xl' => 'center',
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ],

        'attr' => [],
    ],
);

Let’s try to understand what’s happening in this code. Every SP Page Builder addon has an inline editor that’s specific to its features. In this code, we are specifying the fields/features that our custom addon’s inline editor will have.

First, we have to lay out some basic information like the type, name, title, description, etc. of the addon.

  • ‘type' => 'content',   // set the type of the addon
  • 'addon_name' => 'rich_text',   // same as the addon folder name
  • 'title' => 'Rich Text',    // Display name of the addon
  • 'desc' => 'Rich Text Custom addon',    // This text will appear in the tooltip
  • 'category' => 'Custom',     // Let’s create a separate category for our custom addon and name it Custom. 
  •  'icon' => ‘ ’,   //keep it empty so that it can access the icon image we have added in the assets folder. 

Now, let’s add the fields.

Custom Addon Fields

Inside the 'inline' =>, we need to define the fields of our addon’s inline editor. So our Title, Content, and Button are inside the Rich Text Settings tab, so we will add the code for these three fields under the 'rich_text_general_settings'. And after that, we’ve defined the Alignment Option of the addon.

Create the site.php File

Once our fields are ready, we need to add code to visualize our addon. To do that, inside the rich_text folder let’s create another file, name it site.php, and paste the following code snippet.

<?php
/**
 * @package SP Page Builder
 * @author JoomShaper http://www.joomshaper.com
 * @copyright Copyright (c) 2010 - 2022 JoomShaper
 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
 */
//no direct access
defined('_JEXEC') or die('Restricted access');

class SppagebuilderAddonRich_text extends SppagebuilderAddons
{
 /**
 * The addon frontend render method.
 * The returned HTML string will render to the frontend page.
 *
 * @return string The HTML string.
 * @since 1.0.0
 */
 public function render()
 {
 $settings = $this->addon->settings;
 $class = (isset($settings->class) && $settings->class) ? ' ' . $settings->class : '';
 $title = (isset($settings->title) && $settings->title) ? $settings->title : '';
 $heading_selector = (isset($settings->heading_selector) && $settings->heading_selector) ? $settings->heading_selector : 'h2';
 $content = (isset($settings->content) && $settings->content) ? $settings->content : '';
 $button = (isset($settings->button) && $settings->button) ? $settings->button : '';
 $button_type = (isset($settings->type) && $settings->type) ? $settings->type : '';

 $output = '';

 // Link Parse
 list($link, $target) = AddonHelper::parseLink($settings, 'url');

 $output .= '<div class="sppb-addon sppb-addon-rich_text' . $class . '">';

 // Title
 $output .= '<' . $heading_selector . ' class="sppb-addon-title">';
 $output .= nl2br($title);
 $output .= '</' . $heading_selector . '>';

 // Content
 $output .= '<p>' . $content . '</p>';

 // Button
 $output .= !empty($link) ? '<a ' . $target . ' href="' . $link . '">' : '';
 $output .= '<button class="sppb-btn sppb-btn-' . $button_type . '">' . $button . '</button>';
 $output .= !empty($link) ? '</a>' : '';

 $output .= '</div>';

 return $output;
 }

 /**
 * Generate the CSS string for the frontend page.
 *
 * @return string The CSS string for the page.
 * @since 1.0.0
 */
 public function css()
 {
 $addon_id = '#sppb-addon-' . $this->addon->id;
 $cssHelper = new CSSHelper($addon_id);

 $css = '';

 $settings = $this->addon->settings;
 $settings->alignment = CSSHelper::parseAlignment($settings, 'alignment');
 $alignment = $cssHelper->generateStyle('.sppb-addon.sppb-addon-rich_text', $settings, ['alignment' => 'text-align'], false);

 $css .= $alignment;

 return $css;
 }

 /**
 * Generate the lodash template string for the frontend editor.
 *
 * @return string The lodash template string.
 * @since 1.0.0
 */
 public static function getTemplate()
 {
 $lodash = new Lodash('#sppb-addon-{{ data.id }}');

 // Inline Styles
 $output = '<style type="text/css">';
 $output .= $lodash->alignment('text-align', '.sppb-addon-rich_text', 'data.alignment');
 $output .= '</style>';

 $output .= '
 <#
 let btnUrl = "";
 let target = "";
 let rel = "";
 if (!_.isEmpty(data.url) && _.isObject(data.url)){
 const {url, page, menu, type, new_tab, nofollow} = data?.url;
 if(type === "url") btnUrl = url;
 if(type === "menu") btnUrl = menu;
 if(type === "page") btnUrl = page ? `index.php?option=com_sppagebuilder&view=page&id=${page}` : "";
 
 target = new_tab ? "_blank": "";
 rel = nofollow ? "noopener noreferrer": "";
 }
 
 #>
 ';

 $output .= '<div class="sppb-addon sppb-addon-rich_text {{ data.class}}">';

 // Title
 $output .= '<{{ data.heading_selector }} class="sppb-addon-title">';
 $output .= '<span class="sp-inline-editable-element" data-id={{data.id}} data-fieldName="title" contenteditable="true">{{{ data.title }}}</span>';
 $output .= '</{{ data.heading_selector }}>';

 // Content
 $output .= '<p>';
 $output .= '<span class="sp-inline-editable-element" data-id={{data.id}} data-fieldName="content" contenteditable="true">{{{ data.content }}}</span>';
 $output .= '</p>';

 // Button
 $output .= '<a href=\'{{ btnUrl }}\' target=\'{{ target }}\' rel=\'{{ rel }}\'>';
 $output .= '<button id="btn-{{ data.id }}" class="sppb-btn sppb-btn-{{ data.type }}">';
 $output .= '<span class="sp-inline-editable-element" data-id={{data.id}} data-fieldName="button" contenteditable="true" data-placeholder="Add text...">{{{ data.button }}}</span>';
 $output .= '</button>';
 $output .= '</a>';

 $output .= '</div>';

 return $output;
 }
}

Here, we’ve created a class and named it ‘SppagebuilderAddonRich_text’ which extends the abstract class SppagebuilderAddons. From the class name, you need to replace Rich_text with your addon name. Inside this class, we’ve added three functions:

  • render () - displays the end result
  • css () - controls the style of the end result
  • getTemplate () - allows front-end editing

Inside these functions, replace the div “sppb-addon-rich-text” with your addon’s name. Example: “sppb-addon-your_addon_name.

Step 6: Create the Installable Zip File

Alright, we are almost done! Now, save all your hard work and create a zip file of the project folder plg_sppagebuilder_demo. To create a Zip file, right-click on the folder and click on compress “plg_sppagebuilder_demo” and you're done.

Step 7: Install the Plugin

The plugin that we have created can be installed on your website like any other Joomla plugin. Go to Joomla Backend > System > Install > Extension > Upload Package File.

After the installation, you need to activate (publish) the plugin. To do that, from the Joomla Backend go to System > Manage > Extensions. Find your plugin (type demo in the search) and hit publish.

Final Output

Congratulation! You’ve successfully created your own custom addon. To access the addon, go to the editing mode of a page with SP Page Builder. Here under the Custom Category, you will be able to see your custom addon.

Wrapping Up

We hope this article helped you learn how to easily create a custom addon in SP Page Builder. While the entire process may seem daunting at first, give it a try. Play around with the code. Once you have the process figured out, you can tailor any custom addon to meet your needs. You can also download the source code for this custom addon to accelerate your custom addon development process. 

For any queries or assistance, feel free to reach out to us in the comments. Good Luck!

Try SP Page Builder for FREE!Get SP Page Builder Pro

Zareen Tasnim

Zareen Tasnim

Technical Content Writer
Zareen is a technical content writer at JoomShaper. She's a tech enthusiast, writer by day, programmer by night, and always a foodie at heart!
Dmitry Goncharov
Dmitry Goncharov
1 month ago
How can I make my own DIV addon?
Dmitry Goncharov
Dmitry Goncharov
1 month ago
There is a need to create your own DIV addons to expand functionality. The current DIV addon supports flex, but I need grid.
Saam
Saam
1 month ago
answering your own question. This is how support should work ;-)

cheers.
AK
Antonis Kolitsopoulos
1 month ago
Small typo on demo.php

defined('_JEXEC') or die('Restricted Access);
--->
defined('_JEXEC') or die('Restricted Access');

Also if you just copy paste the snipplets make sure you update the file demo.xml tag to a normal email , seems there is a rogue javascript that pasted itself in there for no apparent reason :)

Thanks for the article
Cheers

Dmitry Goncharov
Dmitry Goncharov
1 month ago
Faced with a serious problem that makes it impossible to create your own addons.

https://www.joomshaper.com/forum/question/18779
Dmitry Goncharov
Dmitry Goncharov
1 month ago
Is there any information?
Zareen Tasnim
Zareen Tasnim
3 weeks ago
Please try again with the latest SP Page Builder, v4.0.6. This should be fixed after the last update.

Sign up for our newsletter

Don’t miss any updates of our new templates and extensions and all the astonishing offers we bring for you.