25
loading...
This website collects cookies to deliver better user experience
This post is part of a series about auto-tagging
settings
object, a view should be used to provide additional details about the feature.npx @adobe/reactor-scaffold
src
folder is automatically generated for us. Inside this folder you will find the lib
and view
folder.view
folder should contain all the HTML files which will be used in the Adobe Launch UI. When an extension is installed, Adobe Launch will allow you to use the actions, data elements etc... that you configured in your extension.json
file. When you select in the Adobe Launch interface one of the features that you configured, Adobe Launch will fetch the corresponding HTML file and load it in an iframe. The main purpose of a view is to return a settings
object that will then be used in the JavaScript file present in the lib
folder.lib
folder will be present in the Adobe Launch core library that you load on your website.Try to remove the .min
from your Adobe Launch library URL and have a look. You will see the content of your js files inside it.
view
folder itself. This way when you will use npx @adobe/reactor-packager
command, they will automatically be zipped.Please note that while some public extensions available in Adobe Launch use Single Page Application framework like React to create the Views, you do not have to use any. I use default HTML, CSS and Vanilla JavaScript and it meets all my requirements.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Extension Configuration</title>
</head>
<body>
Extension Configuration Template
<script src="https://assets.adobedtm.com/activation/reactor/extensionbridge/extensionbridge.min.js"></script>
<script>
window.extensionBridge.register({
init: function(info) {
if (info.settings) {
// TODO Populate form values from persisted settings.
}
},
getSettings: function() {
// TODO Return settings object from form values.
},
validate: function() {
// TODO Return whether settings are valid.
}
});
</script>
</body>
</html>
Extension Configuration Template
. This section can be replaced by any HTML code that you want. You can style as you want as well. Usually, you will place your configuration form in this section.true
should be returned if validation is a success and false
should be returned if validation is a failure.validate: function() {
return true;
}
settings
object which contains the configuration that will be used in the js file for the rule or data element or condition or extension.getSettings: function() {
return {
test1: getValueFromField1(),
test2: 123,
test3: [1, 3]
}
},
getSettings
section. The validate
section should be used instead. Also, you should always have corresponding validation logic inside your js file to make sure the settings
object is as you would expect. settings
object exist. If it exists, you can then prepopulate the form with the existing configuration.init: function(info) {
if (info.settings) {
if (info.settings.test1) {
test1Field.value = info.settings.test1;
}
}
},
window.extensionBridge.register({
init: function(info) {},
getSettings: function() {
return {};
},
validate: function() {
return true;
}
});
npx @adobe/reactor-packager
view
folder. If they are outside there will not be available when the view HTML files loads in Adobe Launch.css
folder in the view
folderjs
folder in the view
folderhelpers
folder in the js
folderAdd the file viewHelpers.js
inside the js/helpers
folder
//Support selection of data element
function addListenerToDataElement() {
var dataElementSelectorElements = document.querySelectorAll('.data-element');
if (dataElementSelectorElements) {
dataElementSelectorElements.forEach(function (element) {
element.addEventListener('click', function (event) {
window.extensionBridge.openDataElementSelector().then(function (dataElement) {
var target = event.target;
while (!target.classList.contains('field')) {
target = target.parentElement;
}
target.querySelector('.input').value = dataElement;
});
});
})
}
}
addListenerToDataElement();
//used when missing field
function toggleNotification() {
document.querySelector('#error').classList.toggle('is-hidden');
}
The folder structure should now look as follow
> src
> view
> actions
> dataElements
> configuration
> events
> css
bulma.min.js
> js
> helpers
viewHelpers.js
Go to your html files and update them to reference your CSS file and JavaScript files
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Extension Configuration</title>
<link rel="stylesheet" href="../css/bulma.min.css">
<script src="https://unpkg.com/[email protected]/dist/ionicons.js"></script>
</head>
<body>
<section class="section is-hidden" id="error">
<div class="notification is-danger is-light">
<button class="delete" onclick="toggleNotification()"></button>
<ion-icon name="alert" class="has-text-danger"></ion-icon> Error message
</div>
</section>
<script src="https://assets.adobedtm.com/activation/reactor/extensionbridge/extensionbridge.min.js"></script>
<script>
window.extensionBridge.register({
init: function (info) { },
getSettings: function () {
return {};
},
validate: function () {
return true;
}
});
</script>
<script src="../js/helpers/viewHelpers.js"></script>
</body>
</html>
settings
object with the configuration to be used when the action or data element or condition or extension is executed.settings
: %
as %myDataElement%
We will use the openDataElementSelector
and openCodeEditor
shared views to edit our code.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Extension Configuration</title>
<link rel="stylesheet" href="../css/bulma.min.css">
<script src="https://unpkg.com/[email protected]/dist/ionicons.js"></script>
</head>
<body>
<section class="section is-hidden" id="error">
<div class="notification is-danger is-light">
<button class="delete" onclick="toggleNotification()"></button>
<ion-icon name="alert" class="has-text-danger"></ion-icon> Error message
</div>
</section>
<section>
<!--Normal field-->
<label class="label">Normal Field</label>
<div class="field">
<div class="control is-expanded">
<input id="normal" class="input" type="text" placeholder="Input a value">
</div>
</div>
<!--Field with Data Element selection-->
<label class="label">Data Element Selection field</label>
<div class="field has-addons">
<div class="control is-expanded">
<input id="dataElement" class="input" type="text" placeholder="Click on icon to select your data element">
</div>
<div class="control">
<a class="button is-info data-element">
<span class="icon is-small">
<ion-icon name="reorder"></ion-icon>
</span>
</a>
</div>
</div>
<!--Button to edit JSON config-->
<button class="button is-medium is-outlined is-info" id="edit-config" onClick="editConfig()">
<span class="icon is-large is-primary">
<ion-icon name="code"></ion-icon>
</span>
<span>Edit Config</span>
</button>
<!--Button to edit custom code-->
<button class="button is-medium is-outlined is-info" id="edit-function" onClick="editFunction()">
<span class="icon is-large is-primary">
<ion-icon name="code"></ion-icon>
</span>
<span>Edit Function</span>
</button>
</section>
<script>
/**
* Will open a code editor to edit the JSON value
*/
function editConfig() {
window.extensionBridge.openCodeEditor({
code: window.config.source,
language: 'json'
}).then(function (code) {
window.config.source = code;
});
}
/**
* Will open a code editor to edit the custom code
*/
function editFunction() {
window.extensionBridge.openCodeEditor({
code: window.customCode.source,
language: 'javascript'
}).then(function (code) {
window.customCode.source = code;
});
}
</script>
<script src="https://assets.adobedtm.com/activation/reactor/extensionbridge/extensionbridge.min.js"></script>
<script>
window.customCode = { source: '' } //Stores custom code to be displayed in code editor
window.config = { source: '' } //Stores custom JSON config to be displayed in code editor
var normal = document.querySelector('#normal');
var dataElement = document.querySelector('#dataElement');
window.extensionBridge.register({
// We need to remember to prepopulate the config forms so we can edit saved data
init: function (info) {
if (info.settings) {
if (info.settings.normal) {
normal.value = info.settings.normal;
}
if (info.settings.dataElement) {
dataElement.value = info.settings.dataElement;
}
if (info.settings.config) {
window.config.source = info.settings.config;
}
if (info.settings.customCode) {
window.customCode.source = info.settings.customCode;
}
}
},
//We will return a custom object that will be available in the settings object during runtime
getSettings: function () {
return {
normal: normal.value,
dataElement: dataElement.value,
config: window.config.source,
customCode: window.customCode.source
};
},
validate: function () {
return true;
}
});
</script>
<script src="../js/helpers/viewHelpers.js"></script>
</body>
</html>
tranforms
in the extension.json
file. In our case we want our custom code to be stored in a function so that we can execute it. By default, any custom code using the code editor will be stored as a String in the settings
object.transforms
property for the view:"configuration": {
"viewPath": "configuration/configuration.html",
"schema": {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {}
},
"transforms": [{
"type": "function",
"propertyPath": "customCode",
"parameters": ["window", "anotherArgument", "anotherOne"]
}]
},
Notice that you can specify more than one transform action. In our case we are using a type of function
on the settings property customCode
. We also specify that the function can have 3 arguments when it is called.
settings
object will be saved when the main Adobe Launch library has been built.Check the Adobe Launch library URL without the .min and you should see how the settings object is saved.
view
folder (i.e: an action will be saved in the actions
folder)lib
folder (i.e: an action will be saved in the actions
folder). The file will have the same name but with an extension of .js
extension.json
that tells which view to use and which corresponding js file to use.Notice that by default the configuration view for the extension will not generate a js file. You will need to create one and reference it in the extension.js
file in the main
property.
'use strict';
module.exports = function(settings) {
// TODO Perform some action.
};
Conditions also have a trigger
argument.
event
. Adobe Launch has it owns event
object which can be leveraged in your code. It provides details about what type of rule is being used to trigger this action but it also provides event.detail
which contains the metadata provided as payload when a direct call rule is triggered._satellite.track('myDCR', { test: 123, prop1: ['a', 'b']})
event
argument we will lose this payload. Even if you are not planning to use the event
object, it is still a best practice to reference it. If you omit it, any data element which rely on the event
object will not return the correct data. So you reference it for other features to use it.You can call a data element in the code using _satellite.getVar('myDataElement', event)
and in the data element view you can leverage the event
object using %event.detail.test%
'use strict';
module.exports = function(settings, event) {
// TODO Perform some action.
};
settings
object passed as argument to a function. You will need to use turbine.getExtensionSettings()
in your extension code to leverage the extension settings. This can be used in any JavaScript file of your extension.settings
configured to use in your code. Developing your own private extension will allow you to save a lot of time while tagging.