TL;DR: This article is a step by step guideline for the advance users of SP Page Builder (the most popular Joomla Page Building tool). 

If you’re using SP Page Builder for a while and the thought of creating your own addon popped up in your mind. You had probably put a “period” on that thought thinking since you are not a professional developer, you cannot do it. Well, this is where you’re wrong. You can both create your own addon and make money out of it by selling.

As it turns out, you don’t have to be a professional developer or the creator of SP Page Builder to have your own addon. If you know a thing or two about programming and can write functions to execute your desired task. You can create a custom addon for SP Page Builder any day you want.

Steps for creating a custom addon

The source code is attached at the end of this article but to understand the process better, we’ll see a step by step guide for creating a custom addon from scratch.

Note: We will be using “Sample Addon” as the name of our new addon.

Step 1: Creating the plugin

Before we begin, we need to first understand that there would be a plugin using which our custom addon(s) will be installed. So first, we need to create a plugin. Creating a plugin is pretty simple, you just create a folder, then put necessary files inside and create a zip file out of it. That zip file is the installable plugin. Here's what would be inside the plugin folder:

  • The PHP file that would be used as installer
  • The supporting XML file for the plugin
  • The folder that will store the addon(s) 

We'll follow the standard naming practice and it is important that we strictly follow the naming convention since it's case sensitive. We would create a folder named  plg_sppagebuilder_demo here demo is the plugin name.

Step 2: Creating plugin-specific files

We'll start by creating the plugin PHP file. To do that, open your text/code editor, create a new file, and this is important, name the file according to the plugin name. Here, the plugin name is Demo, hence the name of the file would be demo.php then paste the following code snippet. 

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

//no direct accees
defined('_JEXEC') or die('Restricted Aceess');

class PlgSppagebuilderDemo extends JPlugin {
	protected $autoloadLanguage = true;
}

You should rename the PlgSppagebuilderDemo class to your preferred one, Demo is the name of the plugin, thus it's the word you’ll be replacing.

Once we did that, we'll create a new XML file for our plugin. The process is similar, 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 Nov 2019</creationDate>
	<authorEmail>support(at)joomshaper.com</authorEmail>
	<authorUrl>https://www.joomshaper.com</authorUrl>
	<copyright>Copyright (C) 2010 - 2019 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>

You should replace three words in this code. Firstly, in the <name> tag put the name of your addon. Secondly, and this is the important part, in the <filename> tag replace the file name demo.php with your plugin PHP file. In the <folder> tag set the folder name "addons" in this case (relate to step 3).

Note: All characters must be in lowercase and use underscore instead of space.

Step 3: Creating the addon folder

Once we have created both plugin-specific files PHP and XML, we’ll create a folder in which we will put all the addons. Yes, a plugin can be used for installing multiple addons. The addons we will be creating would be stored in the folder "addons". Create separate folders for each addons (if you wish to create more than one). Therefore, inside the “addons” folder, we’ll create a folder with the name of our custom addon. We have named our first addon as Sample Addon, hence the folder name is “sample_addon”.

How to Create a Custom Addon for SP Page Builder

Figure: File structure for creating your custom addon.

Our addon folder will host two files and a folder. The admin.php file is responsible for creating the addon fields (aka the functionalities of the addon), the site.php file is used for visualizing the addon. There would also be a folder in which we will store all the assets for the addon, hence we name it "assets". In the next step, we'll be writing the functionalities for the addon. 

Step 4: Writing functions for the addon

So, when we are done laying the basics, we’ll start writing code to add fields (features) in our addon. Let’s create a new PHP file 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 - 2019 JoomShaper
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
*/

//no direct accees
defined('_JEXEC') or die('Restricted Aceess');

SpAddonsConfig::addonConfig(
	array(
		'type'=>'content',
		'addon_name'=>'sample_addon',
		'title'=> 'Sample Addon',
		'desc'=> 'Sample addon for SP Page Builder (Now you can edit or modify this)',
		'icon'=>JURI::root() . 'plugins/sppagebuilder/demo/addons/sample_addon/assets/images/icon.png',
		'category'=>'MyAddons',
		'attr'=>array(
			'general' => array(
				'admin_label'=>array(
					'type'=>'text',
					'title'=>JText::_('COM_SPPAGEBUILDER_ADDON_ADMIN_LABEL'),
					'desc'=>JText::_('COM_SPPAGEBUILDER_ADDON_ADMIN_LABEL_DESC'),
					'std'=> ''
				),
				// Title
				'title'=>array(
					'type'=>'textarea',
					'title'=>JText::_('COM_SPPAGEBUILDER_ADDON_TITLE'),
					'desc'=>JText::_('COM_SPPAGEBUILDER_ADDON_TITLE_DESC'),
					'std'=>  'This is sample title'
				),
				'addon_icon'=>array(
					'type'=>'icon',
					'title'=>'Icon',
					'depends'=>array(array('title', '!=', '')),
				),
				'addon_link'=>array(
					'type'=>'media',
					'format'=>'attachment',
					'title'=>'Link',
					'placeholder'=>'http://',
					'std'=>'',
					'hide_preview'=>true,
				),
				'addon_font_family'=>array(
					'type'=>'fonts',
					'title'=>'Font Family',
					'depends'=>array(array('title', '!=', '')),
					'selector'=> array(
						'type'=>'font',
						'font'=>'{{ VALUE }}',
						'css'=>'.sppb-addon-title { font-family: {{ VALUE }}; }'
					)
				),
				'addon_fontsize'=>array(
					'type'=>'slider',
					'title'=>'Font Size',
					'std'=>'',
					'max'=>400,
					'responsive'=>true
				),
				'addon_lineheight'=>array(
					'type'=>'slider',
					'title'=>'Line Height',
					'std'=>'',
					'max'=>400,
					'responsive'=>true
				),

				'addon_font_style'=>array(
					'type'=>'fontstyle',
					'title'=>'Font Style',
					'depends'=>array(array('title', '!=', '')),
				),
				'addon_margin'=>array(
					'type'=>'margin',
					'title'=>'Margin',
					'std' => '0px 0px 30px 0px',
					'responsive'=>true
				),
				'addon_padding'=>array(
					'type'=>'padding',
					'title'=>'Padding',
					'std' => '0px 0px 0px 0px',
					'responsive'=>true
				),

				// Content
				'content'=>array(
					'type'=>'editor',
					'title'=>JText::_('COM_SPPAGEBUILDER_GLOBAL_CONTENT'),
					'std'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer adipiscing erat eget risus sollicitudin pellentesque et non erat. Maecenas nibh dolor, malesuada et bibendum a, sagittis accumsan ipsum. Pellentesque ultrices ultrices sapien, nec tincidunt nunc posuere ut. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam scelerisque tristique dolor vitae tincidunt. Aenean quis massa uada mi elementum elementum. Nec sapien convallis vulputate rhoncus vel dui.'
				),

				'class'=>array(
					'type'=>'text',
					'title'=>JText::_('COM_SPPAGEBUILDER_ADDON_CLASS'),
					'desc'=>JText::_('COM_SPPAGEBUILDER_ADDON_CLASS_DESC'),
					'std'=>''
				),

			),
		),
	)
);

This is the file where you’d be writing feature-specific code for your addon. Define the value for 'addon_name' - this must be same as the addon folder, 'title' - is the name of the addon, 'desc' - is the text shown in the tooltip, 'icon' - is the link for the icon, 'category' - to create a separate category for our addon(s), and then start writing features for the addon. The 'general' array is where you write the fields (aka functions) for the addon. 

The following fields are coming from the admin.php file.

How to Create a Custom Addon for SP Page Builder

Once we have done that, we need to visualise our addon, and that's the whole point. For that purpose, we need to create a new file then paste the following code snippet into that file, name it site.php.

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

//no direct accees
defined('_JEXEC') or die('Restricted Aceess');

class SppagebuilderAddonSample_addon extends SppagebuilderAddons {

    public function render() {
        $class      = (isset($this->addon->settings->class) && $this->addon->settings->class) ? ' ' . $this->addon->settings->class : '';
        $title      = (isset($this->addon->settings->title) && $this->addon->settings->title) ? $this->addon->settings->title : '';
        $addon_link = (isset($this->addon->settings->addon_link) && $this->addon->settings->addon_link) ? $this->addon->settings->addon_link : '';
        $addon_icon = (isset($this->addon->settings->addon_icon) && $this->addon->settings->addon_icon) ? $this->addon->settings->addon_icon : '';
        $content    = (isset($this->addon->settings->content) && $this->addon->settings->content) ? $this->addon->settings->content : '';

        $output = '';
        $output .= '<div class="sppb-addon sppb-addon-sample' . $class . '">';
            if($title) {
                $output .= '<h1 class="sppb-addon-title">';
                    $output .= (!empty($addon_link)) ? '<a href="' . $addon_link . '">' : '';
                    $output .= (!empty($addon_icon)) ? '<i class="fa ' . $addon_icon . '"></i> ' : '';
                    $output .= (!empty($title)) ? $title : '';
                    $output .= (!empty($addon_link)) ? '</a>' : '';
                $output .= '</h1>';
            }

            if($content) {
                $output .= '<div class="sppb-addon-content">';
                    $output .= $content;
                $output .= '</div>';
            }
        $output .= '</div>';

        return $output;
    }

    public function css() {
        $addon_id = '#sppb-addon-' . $this->addon->id;

        $style = '';
        $style_sm = '';
        $style_xs = '';

        $style .= (isset($this->addon->settings->addon_margin) && $this->addon->settings->addon_margin) ?  SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_margin, 'margin') : '';
        $style_sm .= (isset($this->addon->settings->addon_margin_sm) && $this->addon->settings->addon_margin_sm) ?  SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_margin_sm, 'margin') : '';
        $style_xs .= (isset($this->addon->settings->addon_margin_xs) && $this->addon->settings->addon_margin_xs) ?  SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_margin_xs, 'margin') : '';

        $style .= (isset($this->addon->settings->addon_padding) && $this->addon->settings->addon_padding) ? SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_padding, 'padding') : '';
        $style_sm .= (isset($this->addon->settings->addon_padding_sm) && $this->addon->settings->addon_padding_sm) ? SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_padding_sm, 'padding') : '';
        $style_xs .= (isset($this->addon->settings->addon_padding_xs) && $this->addon->settings->addon_padding_xs) ? SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_padding_xs, 'padding') : '';
        
        $style .= (isset($this->addon->settings->addon_fontsize) && $this->addon->settings->addon_fontsize) ? 'font-size: ' . $this->addon->settings->addon_fontsize  . 'px; ' : '';
        $style_sm .= (isset($this->addon->settings->addon_fontsize_sm) && $this->addon->settings->addon_fontsize_sm) ? 'font-size: ' . $this->addon->settings->addon_fontsize_sm  . 'px; ' : '';
        $style_xs .= (isset($this->addon->settings->addon_fontsize_xs) && $this->addon->settings->addon_fontsize_xs) ? 'font-size: ' . $this->addon->settings->addon_fontsize_xs  . 'px; ' : '';
        
        $style .= (isset($this->addon->settings->addon_lineheight) && $this->addon->settings->addon_lineheight) ? 'line-height: ' . $this->addon->settings->addon_lineheight  . 'px; ' : '';
        $style_sm .= (isset($this->addon->settings->addon_lineheight_sm) && $this->addon->settings->addon_lineheight_sm) ? 'line-height: ' . $this->addon->settings->addon_lineheight_sm  . 'px; ' : '';
        $style_xs .= (isset($this->addon->settings->addon_lineheight_xs) && $this->addon->settings->addon_lineheight_xs) ? 'line-height: ' . $this->addon->settings->addon_lineheight_xs  . 'px; ' : '';

        // Font Style
        if(isset($addon->settings->addon_font_style->underline) && $addon->settings->addon_font_style->underline) {
            $style .= 'text-decoration: underline;';
        }

        if(isset($addon->settings->addon_font_style->italic) && $addon->settings->addon_font_style->italic) {
            $style .= 'font-style: italic;';
        }

        if(isset($addon->settings->addon_font_style->uppercase) && $addon->settings->addon_font_style->uppercase) {
            $style .= 'text-transform: uppercase;';
        }

        if(isset($addon->settings->addon_font_style->weight) && $addon->settings->addon_font_style->weight) {
            $style .= 'font-weight: ' . $addon->settings->addon_font_style->weight . ';';
        }

        $css = '';
        if ($style) {
            $css .= $addon_id . ' .sppb-addon-title {' . $style . '}';
        }

        if ($style_sm) {
            $css .= '@media (min-width: 768px) and (max-width: 991px) {';
                $css .= $addon_id . ' .sppb-addon-title {' . $style_sm . '}';
            $css .= '}';
        }

        if ($style_xs) {
            $css .= '@media (max-width: 767px) {';
                $css .= $addon_id . ' .sppb-addon-title {' . $style_xs . '}';
            $css .= '}';
        }

        return $css;
    }

    public static function getTemplate() {
        $output = '
        <#
            var margin = window.getMarginPadding(data.addon_margin, "margin");
            var padding = window.getMarginPadding(data.addon_padding, "padding");
        #>
        <style type="text/css">
            #sppb-addon-{{ data.id }} .sppb-addon-title{
                <# if(_.isObject(data.addon_fontsize)){ #>
                    font-size: {{ data.addon_fontsize.md }}px;
                <# } #>

                <# if(_.isObject(data.addon_lineheight)){ #>
                    line-height: {{ data.addon_lineheight.md }}px;
                <# } #>

                <# if(_.isObject(data.addon_font_style) && data.addon_font_style.underline) { #>
                    text-decoration: underline;
                <# } #>

                <# if(_.isObject(data.addon_font_style) && data.addon_font_style.italic) { #>
                    font-style: italic;
                <# } #>

                <# if(_.isObject(data.addon_font_style) && data.addon_font_style.uppercase) { #>
                    text-transform: uppercase;
                <# } #>

                <# if(_.isObject(data.addon_font_style) && data.addon_font_style.weight) { #>
                    font-weight: {{ data.addon_font_style.weight }};
                <# } #>
                
                <# if(_.isObject(margin)){ #>
                    {{{ padding.md }}}
                    {{{ margin.md }}}
                <# } #>
            }

            @media (min-width: 768px) and (max-width: 991px) {
                #sppb-addon-{{ data.id }} .sppb-addon-title{
                    <# if(_.isObject(margin)){ #>
                        {{{ padding.sm }}}
                        {{{ margin.sm }}}
                    <# } #>
                }
            }
            @media (max-width: 767px) {
                #sppb-addon-{{ data.id }} .sppb-addon-title{
                    <# if(_.isObject(margin)){ #>
                        {{{ padding.xs }}}
                        {{{ margin.xs }}}
                    <# } #>
                }
            }
        </style>
        <div class="sppb-addon sppb-addon-hello-world {{ data.class }}">
            <h1 class="sppb-addon-title">
                <# if(!_.isEmpty(data.addon_link)){ #>
                    <a href="/{{ data.addon_link }}">
                <# } #>
                <# if(!_.isEmpty(data.addon_icon)){ #>
                    <i class="fa {{ data.addon_icon }}"></i> 
                <# } #>
                {{{ data.title }}}
                <# if(!_.isEmpty(data.addon_link)){ #>
                    </a>
                <# } #>
            </h1>
            <# if(!_.isEmpty(data.content)){ #>
                <div id="addon-sample-{{data.id}}" class="sppb-addon-content sp-editable-content" data-id={{data.id}} data-fieldName="content">{{{ data.content }}}</div>
            <# } #>
        </div>
        ';

        return $output;
    }
}

The important thing to do here is to change the class name from “SppagebuilderAddonSample_addon” to “SampleBuilderAddonYour_addon” and whenever you are going to name a div, use this format “sppb-addon-sample-addon”.

The following output is coming from the site.php file.

How to Create a Custom Addon for SP Page Builder

To explain the code of the site.php file: the render() function shows the end result, the css() controls the style of the end result, and finally, the getTemplate() function is used for providing front-end editing support. If you don't want to include live editing (aka frontend editing) for your addon, you can replace the getTemplate() function with the following code. 

public static function getTemplate() {
        return false;
    }

Finally, as for the assets folder, this is where we store the addon icon. It's an image file, so we create an "images" folder and put the icon there. The size of the icon is 76*76 px and the name is icon.png. If you want to change the icon just replace the icon image. For your reference, the path is sample_addon > assets > images > icon.

Step 5: Creating the installable (zip) file.

When you are done with all the above steps, you need to create a zip file. Just simply compress the plg_sppagebuilder_demo folder and you're done. The plugin can be installed on your website like any other Joomla Plugins by going to Joomla backend > Extensions > Manage > Install > Upload Package File.

How to Create a Custom Addon for SP Page Builder

Finally, after installation, you need to activate (publish) the plugin, by going to Extensions > Plugins > find your plugin and publish.

How to Create a Custom Addon for SP Page Builder

Repeat the process to create multiple addons and install them using only one plugin. 

If you think it's too much of a work, you can just download the following source code. Then start making changes stated in the above steps. And of course, if you find any difficulties following these instructions or need assistance in creating your own. Feel free to reach us in the comments below, we are always here to help.

Download The Source Code!    Get SP Page Builder Pro!