Expand my Community achievements bar.

SOLVED

Adobe Launch private extension code editor

Avatar

Community Advisor

I have a private extension and I am trying to use the extension bridge for code editor.

When the code is saved I want that the code saved is saved as a function in the settings.

 

function editConfig() {
    window.extensionBridge.openCodeEditor({
        language: 'javascript'
    }).then(function(code) {
        //source property needs to be a function
        window.customCode = {
            source: function(window) {
               code
            }
        }
    });
}

 

 

However when I look at the window.customCode.source I can see that the body of the function does not contain the value of code from editor but just


ƒ (window) {
code
}

I am using vanilla javascript in my project. Should I be using new Function('window', code) ?

I would like to obtain same functionality as in the code editor for the data element action from the core extension.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

After testing I can confirm that you can use the following in your extension.json file

 

"transforms": [
    {
        "type": "function",
        "propertyPath": "source",
        "parameters": ["event"]
    }
]

You need to place it at the same level as schema

"configuration": {
    "viewPath": "configuration/configuration.html",
        "schema": {
        "$schema": "http://json-schema.org/draft-04/schema#",
            "type": "object",
                "properties": { }
    },
    "transforms": [
        {
            "type": "function",
            "propertyPath": "source",
            "parameters": ["event"]
        }
    ]
},

In my extension the on edit button I call this function:

function editConfig() {
    window.extensionBridge.openCodeEditor({
        code: window.customCode.source,
        language: 'javascript'
    }).then(function (code) {
        window.customCode.source = code;
    });
}

This is configuration in extension bridge

window.extensionBridge.register({
    init: function (info) {
        if (info.settings) {
            if (info.settings.source) {
                window.customCode.source = info.settings.source;
            }
        }
    },

    getSettings: function () {
        return {
            source: window.customCode.source
        }
    },

    validate: function () {
        return true;
    }
});

When I enter this code and I save in my configuration view:

var x = 123;
return x;

When the build is successfully completed I can see the following in the library:

"settings": {
    "source": function(event) {
        var x = 123;
        return x;
    }
}

This is documented here: https://experienceleague.adobe.com/docs/experience-platform/tags/extension-dev/manifest.html?lang=en

 

Function transform

The function transform allows code written by Platform users to be executed by a library module within the emitted tag runtime library.

Let’s assume we would like to provide a “custom script” action type. The “custom script” action view might provide a textarea wherein the user can enter some code. Let’s assume a user entered the following code into the textarea:

console.log('Welcome, ' + username +'. This is ZomboCom.');

When the user saves the rule, the settings object saved by the view may look like this:

{
  foo: {
    bar: "console.log('Welcome, ' + username +'. This is ZomboCom.');"
  }
}
 

When a rule using our action fires within the tag runtime library, we would like to execute the user’s code and pass it a username.

At the point that the settings object is saved from the action type’s view, the user’s code is simply a string. This is good because it can be properly serialized to and from JSON; however, it’s also bad because it would typically be emitted in the tag runtime library as a string as well instead of an executable function. Although you could attempt to execute the code within your action type’s library module using eval or a Function constructor, it is highly discouraged due to content security policies potentially blocking execution.

As a workaround for this situation, using the function transform tells Platform to wrap the user’s code in a executable function when it is emitted in the tag runtime library. To solve our example problem, we would define the transform on the type definition in extension.json as follows:

{
  "transforms": [
    {
      "type": "function",
      "propertyPath": "foo.bar",
      "parameters": ["username"]
    }
  ]
}
 
  • type defines the type of transform that should be applied to the settings object.
  • propertyPath is a period-delimited string that tells Platform where to find the property that needs to be modified within the settings object.
  • parameters is an array of parameter names that should be included in the wrapping function’s signature.

When the settings object is emitted in the tag runtime library, it will be transformed to the following:

{
  foo: {
    bar: function(username) {
      console.log('Welcome, ' + username +'. This is ZomboCom.');
    }
  }
}
 

Your library module can then call the function containing the user’s code and pass in the username argument.

View solution in original post

3 Replies

Avatar

Community Advisor

I looked at the source code of the core extension https://github.com/adobe/reactor-extension-core and based on what I could see so far the data element for custom code, the only thing that would transform the code to a function like so in the compiled launch library: 

 

"test": {
    "modulePath": "core/src/lib/dataElements/customCode.js",
        "settings": {
        "source": function(event) {
            console.log('test', _satellite.getVar('payload', event));
            return "123"
        }
    }
},

If this configuration in the extension.json

"transforms": [
    {
        "type": "function",
        "propertyPath": "source",
        "parameters": ["event"]
    }
]

I am in the process of testing this in my extension.

Avatar

Correct answer by
Community Advisor

After testing I can confirm that you can use the following in your extension.json file

 

"transforms": [
    {
        "type": "function",
        "propertyPath": "source",
        "parameters": ["event"]
    }
]

You need to place it at the same level as schema

"configuration": {
    "viewPath": "configuration/configuration.html",
        "schema": {
        "$schema": "http://json-schema.org/draft-04/schema#",
            "type": "object",
                "properties": { }
    },
    "transforms": [
        {
            "type": "function",
            "propertyPath": "source",
            "parameters": ["event"]
        }
    ]
},

In my extension the on edit button I call this function:

function editConfig() {
    window.extensionBridge.openCodeEditor({
        code: window.customCode.source,
        language: 'javascript'
    }).then(function (code) {
        window.customCode.source = code;
    });
}

This is configuration in extension bridge

window.extensionBridge.register({
    init: function (info) {
        if (info.settings) {
            if (info.settings.source) {
                window.customCode.source = info.settings.source;
            }
        }
    },

    getSettings: function () {
        return {
            source: window.customCode.source
        }
    },

    validate: function () {
        return true;
    }
});

When I enter this code and I save in my configuration view:

var x = 123;
return x;

When the build is successfully completed I can see the following in the library:

"settings": {
    "source": function(event) {
        var x = 123;
        return x;
    }
}

This is documented here: https://experienceleague.adobe.com/docs/experience-platform/tags/extension-dev/manifest.html?lang=en

 

Function transform

The function transform allows code written by Platform users to be executed by a library module within the emitted tag runtime library.

Let’s assume we would like to provide a “custom script” action type. The “custom script” action view might provide a textarea wherein the user can enter some code. Let’s assume a user entered the following code into the textarea:

console.log('Welcome, ' + username +'. This is ZomboCom.');

When the user saves the rule, the settings object saved by the view may look like this:

{
  foo: {
    bar: "console.log('Welcome, ' + username +'. This is ZomboCom.');"
  }
}
 

When a rule using our action fires within the tag runtime library, we would like to execute the user’s code and pass it a username.

At the point that the settings object is saved from the action type’s view, the user’s code is simply a string. This is good because it can be properly serialized to and from JSON; however, it’s also bad because it would typically be emitted in the tag runtime library as a string as well instead of an executable function. Although you could attempt to execute the code within your action type’s library module using eval or a Function constructor, it is highly discouraged due to content security policies potentially blocking execution.

As a workaround for this situation, using the function transform tells Platform to wrap the user’s code in a executable function when it is emitted in the tag runtime library. To solve our example problem, we would define the transform on the type definition in extension.json as follows:

{
  "transforms": [
    {
      "type": "function",
      "propertyPath": "foo.bar",
      "parameters": ["username"]
    }
  ]
}
 
  • type defines the type of transform that should be applied to the settings object.
  • propertyPath is a period-delimited string that tells Platform where to find the property that needs to be modified within the settings object.
  • parameters is an array of parameter names that should be included in the wrapping function’s signature.

When the settings object is emitted in the tag runtime library, it will be transformed to the following:

{
  foo: {
    bar: function(username) {
      console.log('Welcome, ' + username +'. This is ZomboCom.');
    }
  }
}
 

Your library module can then call the function containing the user’s code and pass in the username argument.

Avatar

Administrator

Thanks @Alexis_Cazes_  for posting the solution as well. Keep up the good work.