Plugin Structure

⌘K
  1. Home
  2. Docs
  3. Developers “How To&...
  4. Plugin Structure

Plugin Structure

This document explains the folder and file structure of custom addons/elements for WPBakery Page Builder, helping developers understand how the plugin is organized and where to find specific functionality.

Reference: WPBakery Dev Example Plugin provides a complete working reference.

Recommended Plugin Structure

Here’s the recommended folder structure for a 3rd-party plugin that adds custom WPBakery elements:

Root Directory Overview

your-wpbakery-elements/
├── your-wpbakery-elements.php    # Main plugin file
├── readme.txt                     # WordPress plugin readme
├── elements/                      # All custom elements
│   ├── basic-box/                # Example: Basic element
│   │   ├── basic-box.php         # Element registration & class
│   │   └── basic-box.tpl.php     # Frontend template
│   ├── pricing-table/            # Example: Element with logic
│   │   ├── pricing-table.php     # Element registration & class
│   │   └── pricing-table.tpl.php # Frontend template
│   └── tabs-container/           # Example: Nested element
│       ├── tabs-container.php    # Parent element
│       ├── tabs-container.tpl.php
│       ├── tab-item/             # Child element
│       │   ├── tab-item.php
│       │   └── tab-item.tpl.php
├── assets/                        # Optional: Element assets
│   ├── css/
│   │   ├── basic-box.css
│   │   └── pricing-table.css
│   ├── js/
│   │   ├── basic-box.js
│   │   └── pricing-table.js
│   └── images/
│       └── icons/
└── includes/                      # Optional: Helper functions
   └── helpers.php
…………

Core Folders Explained

1. Main Plugin File

File: `your-wpbakery-elements.php`

This is the WordPress plugin header file that initializes your custom elements.

You can see an example code here: https://github.com/wpbakery/dev-example/blob/master/dev-example.php

2. /elements/ – Element Files

Each element gets its own directory containing:

File: `elements/{element-name}/{element-name}.php`
- `vc_map()` registration
- Element class (extends `WPBakeryShortCode` or `WPBakeryShortCodesContainer`)
- Asset enqueueing (if element-specific)


File: `elements/{element-name}/{element-name}.tpl.php`
- Frontend HTML template
- Receives `$atts`, `$content`, and `$this` variables

Example structure:

elements/basic-box/
├── basic-box.php       # Registration + Class
└── basic-box.tpl.php   # Template

3. /assets/ – Static Assets (Optional)

Store CSS, JavaScript, and images used by your elements:

assets/
├── css/
│   ├── elements.css          # Combined styles for all elements
│   ├── basic-box.css         # Element-specific styles
│   └── pricing-table.css
├── js/
│   ├── elements.js           # Combined scripts
│   ├── basic-box.js          # Element-specific scripts
│   └── pricing-table.js
└── images/
   ├── icons/
   │   ├── box-icon.svg
   │   └── price-icon.svg
   └── placeholders/
       └── default.png

Best Practice: Combine common CSS/JS into single files to reduce HTTP requests.

4. /includes/ – Helper Functions (Optional)

Common utility functions used across multiple elements:

**File**: `includes/helpers.php`


<?php
/**
* Helper functions for your elements
*/


if ( ! defined( 'ABSPATH' ) ) {
   exit;
}


/**
* Get element asset URL
*/
function your_elements_get_asset_url( $path ) {
   return YOUR_ELEMENTS_URL . 'assets/' . ltrim( $path, '/' );
}


/**
* Sanitize element classes
*/
function your_elements_sanitize_classes( $classes ) {
   if ( is_array( $classes ) ) {
       return implode( ' ', array_map( 'sanitize_html_class', $classes ) );
   }
   return sanitize_html_class( $classes );
}


/**
* Get element template
*/
function your_elements_get_template( $element_name, $atts = [], $content = '' ) {
   $template_path = YOUR_ELEMENTS_PATH . "elements/{$element_name}/{$element_name}.tpl.php";


   if ( file_exists( $template_path ) ) {
       ob_start();
       include $template_path;
       return ob_get_clean();
   }


   return '';
}

 

File Naming Conventions

Element Files

  • Element folder: elements/{element-slug}/
  • Registration file: {element-slug}.php
  • Template file: {element-slug}.tpl.php
  • Example: elements/basic-box/basic-box.php and basic-box.tpl.php

Element Class

  • Pattern: WPBakeryShortCode_{Your}_{Element}_{Base}
  • Example: WPBakeryShortCode_Your_Basic_Box for [your_basic_box]
  • Note: Use underscores, not hyphens, in class names

Element Base (Shortcode Tag)

  • Pattern: {your_prefix}_{element_name}
  • Example: your_basic_box, your_pricing_table
  • Best Practice: Use a unique prefix to avoid conflicts

 

Best Practices

1. Use Unique Prefixes

Always prefix your element base names to avoid conflicts:

✅ Good
‘base’ => ‘acme_pricing_table’

❌ Bad – might conflict with other plugins
‘base’ => ‘pricing_table’

2. Organize by Feature

Group related elements together:

elements/
├── pricing/
│   ├── pricing-table/
│   └── price-box/
└── testimonials/
    ├── testimonial-slider/
    └── testimonial-grid/

3. Check for WPBakery

Always verify WPBakery is active before initializing:

if ( ! defined( 'WPB_VC_VERSION' ) ) {
    // Show admin notice
    return;
}

4. Use Constants

Define plugin paths as constants for easy reference:

define( 'YOUR_ELEMENTS_PATH', plugin_dir_path( __FILE__ ) );
define( 'YOUR_ELEMENTS_URL', plugin_dir_url( __FILE__ ) );

5. Enqueue Assets Conditionally

Only load CSS/JS when elements are actually used on the page.

Was this article helpful to you? No Yes

How can we help?