Developer Information

The Visual CMS can be extended by adding further widgets.

The editor creates short codes from all widgets (similar to BBCode), which it then saves as content. In the frontend these short codes are parsed again, and the corresponding classes are triggered.

Even the usage of custom grid systems is possible. As default, the module uses a slimmed down version of the Bootstrap grid system.

Theme Integration

Currently provided Visual CMS Shortcode Widgets are compatible with Apex theme (and Wave, for Legacy smarty template engine variant). For other themes, minor adjustments may be necessary.

The following information refers to the Twig template engine. If Smarty is used, the information can be found in the documentation for Visual CMS 3.6.

Content Pages

When needed, the two themes content.html.twig and content_plain.html.twig must be extended by two requests (see comment inside the source code: “Customization: …”):


{% capture append = "oxidBlock_content" %}
    {% set oContent = oView.getContent() %}
    {% set tpl = oViewConf.getActTplName() %}
    {% set oxloadid = oViewConf.getActContentLoadId() %}
    {% set template_title = oView.getTitle() %}

    <div class="container-xxl">
        {% if not oContent.oxcontents__ddhidetitle.value %}
            <h1>{{ template_title }}</h1>
        {% endif %}
        <article class="cmsContent pb-5">
            {{ oView.getParsedContent()|raw }}
    {{ insert_tracker({title: template_title}) }}
{% endcapture %}
{% include "layout/page.html.twig" %}

{# Customization: Checking the display of the sidebar #}
{% if sidebar %}
    {% include "layout/page.html.twig" %}
{% else %}
    {% include "layout/page.html.twig" with {sidebar: "Left"} %}
{% endif %}


{% capture append = "oxidBlock_content" %}
    {% set oContent = oView.getContent() %}
    {% set template_title = oView.getTitle() %}
    {% set tpl = oViewConf.getActTplName() %}
    {% set oxloadid = oViewConf.getActContentLoadId() %}

    {# Customization: Checking the display of the heading #}
    {% if not oContent.oxcontents__ddhidetitle.value %}
        <h1>{{ template_title }}</h1>
    {% endif %}

    {{ oView.getParsedContent() }}
    {{ insert_tracker({title: template_title}) }}
{% endcapture %}
{% include "layout/popup.html.twig" %}

More information about Twig in modules can be found here in the developer documentation.

Widget Creation

In case of creating your own Shortcode, make sure the one:

  • Registered in the services.yaml as a separate service

  • Has a shortcode special tag in service description: ‘visualcms.shortcode.tag.twig’ (or ‘visualcms.shortcode.tag.smarty’ if widget supports smarty legacy engine)

  • Extends the OxidEsalesVisualCmsModuleShortCodeBaseShortCode or implements the OxidEsalesVisualCmsModuleContractShortCodeInterface

  • Has unique string value returned by getShortCode() method - the identifier of the shortcode, like “carousel”, “image”, “hero”. You can check example short code GoogleMap in vcms-example repository.

  class: OxidEsales\VcmsExamples\ShortCode\GoogleMap
  tags: [ 'visualcms.shortcode.tag.twig' ]

BaseShortCode usage

The BaseShortCode abstract class provides basic implementation of the OxidEsalesVisualCmsModuleContractShortCodeInterface and has several methods to use in your extended shortcodes.

The following namespace is always required:


A shortcode class is structured as follows:

class Article extends BaseShortCode
  • The class name consists of filename (without extension).

  • The class should always derive from the class BaseShortCode, so that standard properties and methods are taken over.


The BaseShortCode utilizes usage of several attributes, that can be overwritten by your need.

  • $title: Title of the widget (Lang-String)

  • $backgroundColor: Color of the widget in the admin interface

  • $icon: CSS-class for the icon of the widget in the back end (s.

  • $shortCode: Short-code name - the identifier of the shortcode, like “carousel”, “image”, “hero”. This one should be unique.

  • $template: The frontend template of the ShortCode.


protected string $title = 'DD_VISUAL_EDITOR_SHORTCODE_ARTICLE';
protected string $backgroundColor = '#e74c3c';
protected string $icon = 'fa-newspaper-o';
protected string $shortCode = 'article';
protected string $template = '@ddoevisualcms/shortcodes/visualcms_shortcode_article';


  • The setInterfaceOptions() method is called when initializing the widgets in the administration area.

  • Subsequently, the widget options or input fields are set in the administration area.

public function setInterfaceOptions(): void
    $oLang = Registry::getLang();

        'id' => new SelectFromDataOption(
            // Label name
            label: $oLang->translateString('DD_VISUAL_EDITOR_WIDGET_ARTICLE'),
            // Specifies a method which will be used for a live search
            data: 'searchArticle',
            // placeholder name
            placeholder: $oLang->translateString('DD_VISUAL_EDITOR_WIDGET_CHOOSE_ARTICLE'),
            // fields that are also taken into account for a selection (only for type "select")
            dataFields: ['name' => 'label']
        'articletype' => new SelectOption(
            label: $oLang->translateString('DD_VISUAL_EDITOR_WIDGET_ARTICLE_TYPE'),
            values: [
                'grid' => $oLang->translateString('DD_VISUAL_EDITOR_WIDGET_ARTICLE_TYPE_GRID'),
                'line' => $oLang->translateString('DD_VISUAL_EDITOR_WIDGET_ARTICLE_TYPE_LINE'),
            defaultValue: 'grid'
        'name' => new HiddenOption()


Please note, the setOptions() method consumes the array of OxidEsales\VisualCmsModule\Contract\ShortCodeOptionInterface objects. Our currently provided options should cover most of the cases you may need to configure your widgets. If not, feel free adding your own Options, and using them directly in your Shortcode initialization.


The following describes the process for the text widget. When saving a CMS content in the admin, the data is stored in the oxcontent table as follows.

  • The prepareTemplateParams() method is executed when the shortcode is read in the frontend.

  • The $content parameter is reserved for the content widget option.

  • All other values are passed in the array of the second parameter.

public function prepareTemplateParams(string $content, array $params): array
    $frontendController = oxNew(FrontendController::class);

    $listType = $frontendController->getListDisplayType();
    $viewConfig = Registry::get('oxViewConfig');

    if (!$params['articletype']) {
        if (Registry::getConfig()->getTopActiveView()->getClassKey() == 'start') {
            if (($sStartType = $viewConfig->getViewThemeParam('sStartPageListDisplayType'))) {
                $listType = $sStartType;
    } else {
        $listType = $params['articletype'];

    $params = array_merge($params, [
        'listType' => $listType

    return parent::prepareTemplateParams($content, $params);

A text widget configured via the admin is stored in oxcontent as follows:

[text background_color="#875c5c" background_image="vcms_Car_03_Mood_1.png" background_fixed="1" fullwidth="" class=""]some text widget contents[/text].

After parsing this part for the frontend, the BaseShortCode::prepareTemplateParams method is called. It receives the contents of the text widget as $content and other parameters:

array(5) {
    string(7) "#875c5c"
    string(22) "vcms_Car_03_Mood_1.png"
    string(1) "1"
    string(0) ""
    string(0) ""

The “shortcode” and “content” keys come from BaseShortCode::prepareTemplateParams.

We can overwrite the prepareTemplateParams() with additional logic, requiring the parent of prepareTemplateParams().

This array will be given to the shortcode template, and the data will be accessible as regular template variables.


The information can be used, for example, in the text widget template to include user information or to respond to previous user actions. It is also possible to include services in the shortcodes, but the BaseShortCode constructor should be called to handle the initialization of the management interface parameters:

public function __construct(
    protected \OxidEsales\VisualCmsModule\Service\Categories $categoriesService
) {

The information above should be enough to create a shortcode widget. Everything else depends on the complexity of the widget.


All included widgets are open source in the module folder of VisualCMS under src/ShortCode. These can be used as examples.

Override a existing shortcode

If you want to override a existing shortcode then below is example in which we override the Text shortcode and added a additional field Heading given at vcms-example repository.

  class: OxidEsales\VcmsExamples\ShortCode\Text
  tags: [ 'visualcms.shortcode.tag.twig' ]

Override a shortcode template

If you only want to override a template for a shortcode then below is example given at vcms-example repository.

  class: OxidEsales\VisualCmsModule\DataType\ThemeTemplatesConfiguration
    $themeId: 'apex'
      column: '@@oe_vcmsexamples/shortcodes/vcmsexamples_shortcode_column'
      action: '@@oe_vcmsexamples/some_other_template_for_overwriting_the_original_action_template_for_apex'
  tags: [ 'shortcode.themeTemplates' ]

Custom Grid System

In order to use your own custom grid system, only a few changes in the settings are necessary.

  1. Please navigate in the admin area of the eShop to Extensions ‣ Modules ‣ Visual CMS ‣ Settings

  2. Activate the checkbox Use custom grid. This checkbox is located under the point Front end

  3. Enter the prefixes of CSS-classes for your grid system

  4. Enter the maximum number of columns of the grid system

  5. Save

After that, offsets and column widths can no longer be adjusted by Layout settings of the widget, but must be made by dragging and dropping them on the CMS page.



960 Grid System


The grid system of your choice has to have been included into the theme.