Gentics CMS Asset Management

With the feature asset_management it is possible to insert files from asset stores directly. Next to the existing functionality of uploading from user’s local filesystem (which can optionally be disabled) additional asset store selectors can be integrated and provided to the user.

1 Configuration in Gentics CMS

In order to use the feature, it must be first configured in the configuration:


// activate forms
$FEATURE["asset_management"] = true;

// configure asset_management for node with id "1" (consider using a guid for staging)
// or use $NODE_SETTINGS_GLOBAL if all Nodes should recieve the same configuration
$NODE_SETTINGS[1] = array(
    'asset_management' => array(
        // use key for sorting
            // usage and positiong for default behaviour
            'default' => true
            // configure custom
            'celum' => array(
                'label_i18n' => array(
                    'de' => 'Celum verwenden',
                    'en' => 'use Celum'
                'iframeSrcUrl' => '/customer-config/config/asset_management/celum/asset-picker-2.5.1-dist/api/index.html'
        // ...

Additionally the feature must be activated in the Node Features Dialog in the Administration User Interface for all Nodes where it should be avaliable.

Array asset_management contains an arbitrary number of possible external stores. One entry of this array can contain default. If set to true, the default function (uploading from user’s local filesystem) will be available. identifier must be unique within array. label_i18n is the displayed dropdown item label, which can be configured for multiple languages. However, it must be at least configured for english (en). iframeSrcUrl points to the file which starts an external asset management application. It will be running in an iframe within Gentics CMS frontend application. Dropdown menu order reflects the order of the configration array.

Further notes on configuration: With this feature it is possible to hide the upload button entirely by providing only the `default` array with value `false`. However, this is not recommended, as some UI components include the upload button.

The given structure aims towards allowing any asset store integrations. This example follows the implemented use case of CELUM ContentHub asset store integration .

2 Static files

Via iframeSrcUrl any asset store application can be run but must satisfy the following requirements in order to integrate with GCMS UI.

2.1 UI workflow

The iframe will open on a user action intending to select one or more assets (files). Thus, a view displaying a list or tiles of selectable items is expected.

2.2 Styling

Webpage opened in the iframe must have the following styles.

    body {
        overflow-x: hidden;
        padding: 0;
        width: 100%;
        height: 100%;

2.3 Interface to GCMS UI

The user’s asset store selection’s data must be propagated to parent window via JavaScript postmessage API. A stringified array of JSON objects is expected.

// event to be fired when user has accomplished asset selection:
window.parent.postMessage(JSON.stringify(selections), window.opener);

Important note: If stringified JSON objects do not adhere to the following structure, Gentics development needs to implement explicit data mapping. Current implementation only supports the fields in the following sample.

The values of the properties field will be matched to file object properties: when an object property with the respective name is found, the value is saved to the first editable text part of that property. Fields which do not correspond to object properties are ignored.

2.3.1 Sample data

        // asset name
        "name": "myimage.png";
        // allows 'image' or 'file'
        "fileCategory": "image"
        // expected return value of URL is binary data
        "@odata.mediaReadLink": "",
        // the files nice URL
        "niceUrl": "/nice/myimage.png",
        // the files alternate URLs
        "alternateUrls": [ "/alternative/one/myimage.png", "/alternative/two/othername.png" ],
        // additional properties
        "properties": {
            "copyright": "(C) 2000 by me",
            "comment": "Nice image"

2.4 Sample implementation

E. g. CELUM provides an asset selection application called “Asset Picker” and must be adapted similar to the following code. Link to CELUM Asset Picker repository (active account required)

2.4.1 File structure

├── asset_management
│   └── celum
│       └── asset-picker-2.5.1-dist
│           ├── api
│           │   ├── assetPickerApi.js
│           │   ├── index.html <------- Asset Picker application entry point (configured in @iframeSrcUrl@)
│           │   └── samples
│           │       ├── configs
│           │       │   └── defaultConfig.js <------- API access credentials and parameter are configured here (CELUM-specific)
│           │       ├── jquery.js
│           │       └── samples.css
│           └── picker
│               ├── assetPicker.css
│               ├── assetPicker.min.css
│               ├── assetPickerConnector.js
│               ├── assetPickerMerged.min.js
│               ├── config.css
│               ├── config.js
│               ├── fonts
│               │   ├── ...
│               ├── icon_unsupported_filetype.png
│               ├── inactive.png
│               ├── index.html
│               ├── logo.png
│               ├── ooops.png
│               └── templates
│                   ├── ...
2.4.2 index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
    <title>Asset Picker - iFrame</title>
    <META http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge" >

        <!-- API -->
        <script type="text/javascript" src="./assetPickerApi.js"></script>

        <!-- Resources -->
        <script type="text/javascript" src="samples/jquery.js"></script>
        <link rel="stylesheet" href="samples/samples.css"/>

        <!-- GTX override STYLES -->
            body {
                overflow-x: hidden;
                padding: 0;
                width: 100%;
                height: 100%;
            #mask {
                display: none;
                height: unset;
                width: unset;
                position: absolute;
            #sampleDialog {
                display: none;
                z-index: 10;
                background-color: white;
                position: absolute;
                bottom: 0;
                top: 0;
                left: 0;
                right: 0;
                width: 100%;
                border: none;
            #picker-wrap {
                height: 100%;

        <script type="text/javascript">

            ////// GTX override SCRIPT //////

            // sources can live anywhere as long as it's accessible via the same domain - basePath in this case makes sure that samples work out of the box!
            var index = location.href.indexOf('index.html');
            var basePath = index < 0 ? location.href : location.href.substr(0, index);
            var picker = undefined;

            $(function () {

                var mask = $('#mask');
                var dialog = $('#sampleDialog');

                var closePicker = function () {

                // Path to access credetnials to CELUM ContentHub instance
                var configUrl = basePath + '/samples/configs/defaultConfig.js';

                // Get iframeSrcUrl URL query parameters
                var urlParams = new URLSearchParams(;
                var locale = urlParams.get('locale');


                picker = Celum.AssetPicker.create({
                    container: 'picker-wrap',
                    basePath: '../',
                    locale: locale,
                    cssPath: '',
                    jsConfigPath: configUrl,
                    listeners: {
                        transfer: function (id, selections) {
                            window.parent.postMessage(JSON.stringify(selections), window.opener);


        <!-- GTX override MARKUP -->

        <!-- DIALOG which displays the marker -->
        <div id="mask"></div>
        <div id="sampleDialog">
            <div class="header"><span>Asset Picker</span></div>
            <div id="picker-wrap"></div>