Skip to content

Instantly share code, notes, and snippets.

@Stwissel
Last active April 26, 2019 04:36
Show Gist options
  • Save Stwissel/fa899fa1612e6cc45b5366ec0a29d938 to your computer and use it in GitHub Desktop.
Save Stwissel/fa899fa1612e6cc45b5366ec0a29d938 to your computer and use it in GitHub Desktop.
Custom Action for Salesforce Marketing Cloud

Marketing Cloud Custom Action

The flow provides a boilerplate to create a custom action for consumption in Salesforce Marketing Cloud. The flow outputs the data received from marketing cloud in a debug node. So you need to add whatever you want to do at the level of that debug node

Setup

  • You need to open the the Test JWT node and edit the secret. Better: remove it and set the environment variable as described in the node's documentation
  • the endpoint path is /endpoints/demo. If you want to change that you need to edit 2 nodes: config.json and Action Node

Feedback

Always welcome. Twitter @notessensei

[
{
"id": "f013e682.3118f8",
"type": "tab",
"label": "Marketing Cloud",
"disabled": false,
"info": ""
},
{
"id": "a3b117e3.89e008",
"type": "http response",
"z": "f013e682.3118f8",
"name": "",
"statusCode": "",
"headers": {},
"x": 670,
"y": 360,
"wires": []
},
{
"id": "f5dffd18.e3d34",
"type": "http in",
"z": "f013e682.3118f8",
"name": "Configuration node",
"url": "/marketing-cloud/config.json",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 130,
"y": 360,
"wires": [
[
"6b8f953b.a15e5c"
]
]
},
{
"id": "c75cc7a8.cfdec8",
"type": "comment",
"z": "f013e682.3118f8",
"name": "Config File",
"info": "The JSON file that explains to Marketing Cloud what\nthe activity does",
"x": 100,
"y": 320,
"wires": []
},
{
"id": "6b8f953b.a15e5c",
"type": "function",
"z": "f013e682.3118f8",
"name": "config.json",
"func": "let activity = \"demo\";\nlet detailpayload = {\n params : msg.req.params,\n headers : msg.req.headers\n};\nlet host = msg.req.headers.host;\nlet hostURL = (host.substring(0,9)==='localhost') ? 'http://'+host : 'https://'+host;\n\nmsg.payload = {\n \"workflowApiVersion\": \"1.1\",\n \"metaData\": {\n \"icon\": \"/red/images/node-red.png\",\n \"category\": \"customer\",\n \"configOnDrop\": true\n },\n \"type\": \"REST\",\n \"lang\": {\n \"en-US\": {\n \"name\": activity,\n \"description\":activity,\n \"step1Label\": \"Configure Activity\"\n }\n },\n \"arguments\": {\n \"execute\": {\n \"inArguments\": [\n {\n \"CampaignID\": \"\",\n \"ContactKey\": \"{{Contact.Key}}\"\n }\n ],\n \"outArguments\": [\n {\n \"status\": \"\"\n }\n ],\n \"url\": hostURL+\"/endpoints/\"+activity+\"/execute\",\n \"verb\": \"POST\",\n \"body\": \"\",\n \"header\": \"\",\n \"format\": \"json\",\n \"useJwt\": true,\n \"timeout\": 10000\n }\n },\n \"configurationArguments\": {\n \"applicationExtensionKey\": \"mc_uniquekey\",\n \"save\": {\n \"url\": hostURL+\"/endpoints/\"+activity+\"/save\",\n \"verb\": \"POST\",\n \"useJwt\": true\n },\n \"publish\": {\n \"url\": hostURL+\"/endpoints/\"+activity+\"/publish\",\n \"verb\": \"POST\",\n \"useJwt\": true\n },\n \"stop\": {\n \"url\": hostURL+\"/endpoints/\"+activity+\"/stop\",\n \"verb\": \"POST\",\n \"useJwt\": true\n },\n \"validate\": {\n \"url\": hostURL+\"/endpoints/\"+activity+\"/validate\",\n \"verb\": \"POST\",\n \"useJwt\": true\n }\n },\n \"wizardSteps\": [\n {\n \"label\": \"Configure Activity\",\n \"key\": \"step1\"\n }\n ],\n \"userInterfaces\": {\n \"configModal\": {\n \"height\": 500,\n \"width\": 520,\n \"fullscreen\": false\n }\n },\n \"schema\": {\n \"arguments\": {\n \"execute\": {\n \"inArguments\": [],\n \"outArguments\": [\n {\n \"status\": {\n \"dataType\": \"Text\",\n \"direction\": \"out\",\n \"access\": \"visible\"\n }\n }\n ]\n }\n }\n },\n}\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 410,
"y": 360,
"wires": [
[
"a3b117e3.89e008"
]
],
"info": "# Configuration\n\nYou need to adjust the `activity` variable to the \nsame value you specify in the \"Action Node\".\nDefault is \"demo\""
},
{
"id": "c5c130fa.e4b04",
"type": "http response",
"z": "f013e682.3118f8",
"name": "",
"statusCode": "",
"headers": {},
"x": 770,
"y": 660,
"wires": []
},
{
"id": "44a433d4.4ff93c",
"type": "http in",
"z": "f013e682.3118f8",
"name": "Action Node",
"url": "/endpoints/demo/:action",
"method": "post",
"upload": false,
"swaggerDoc": "",
"x": 110,
"y": 680,
"wires": [
[
"32b72ce.89070d4"
]
]
},
{
"id": "979d4b98.cd9b28",
"type": "comment",
"z": "f013e682.3118f8",
"name": "Incoming from Marketing Cloud",
"info": "",
"x": 170,
"y": 640,
"wires": []
},
{
"id": "449433f6.0f9d3c",
"type": "switch",
"z": "f013e682.3118f8",
"name": "Determine action",
"property": "req.params.action",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "save",
"vt": "str"
},
{
"t": "eq",
"v": "publish",
"vt": "str"
},
{
"t": "eq",
"v": "stop",
"vt": "str"
},
{
"t": "eq",
"v": "validate",
"vt": "str"
},
{
"t": "else"
},
{
"t": "eq",
"v": "execute",
"vt": "str"
}
],
"checkall": "false",
"repair": false,
"outputs": 6,
"x": 330,
"y": 740,
"wires": [
[
"739eaf33.de7e2"
],
[
"739eaf33.de7e2"
],
[
"739eaf33.de7e2"
],
[
"739eaf33.de7e2"
],
[
"de462a32.264b48"
],
[
"4d7d3ac9.4f4da4",
"6fddb92b.d54758"
]
]
},
{
"id": "de462a32.264b48",
"type": "template",
"z": "f013e682.3118f8",
"name": "Error Message",
"field": "payload",
"fieldType": "msg",
"format": "json",
"syntax": "mustache",
"template": "\"{ status : 'Error' }\"",
"output": "str",
"x": 580,
"y": 720,
"wires": [
[
"2ff490b7.e7f19"
]
]
},
{
"id": "2ff490b7.e7f19",
"type": "http response",
"z": "f013e682.3118f8",
"name": "Not Found",
"statusCode": "404",
"headers": {},
"x": 790,
"y": 720,
"wires": []
},
{
"id": "4d7d3ac9.4f4da4",
"type": "template",
"z": "f013e682.3118f8",
"name": "Execute status",
"field": "payload",
"fieldType": "msg",
"format": "text",
"syntax": "mustache",
"template": "'{\"status\" : \"OK\"}'",
"output": "str",
"x": 580,
"y": 780,
"wires": [
[
"157cb491.436b7b"
]
]
},
{
"id": "32b72ce.89070d4",
"type": "jwt verify",
"z": "f013e682.3118f8",
"name": "Test JWT",
"alg": [
"HS256"
],
"jwkurl": "",
"secret": "Barbequeue",
"key": "",
"signvar": "payload",
"storetoken": "token",
"x": 140,
"y": 740,
"wires": [
[
"449433f6.0f9d3c"
]
]
},
{
"id": "beca8ce7.95c0a",
"type": "debug",
"z": "f013e682.3118f8",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 470,
"y": 1000,
"wires": []
},
{
"id": "120fbb23.92a515",
"type": "inject",
"z": "f013e682.3118f8",
"name": "",
"topic": "",
"payload": "eyJhbGciOiJIUzI1NiJ9.ewogICAiaW5Bcmd1bWVudHMiIDogW3sKICAgICJDYW1wYWlnbklEIjogIjcwMTdGMDAwMDAwTUo0T1FBVyIsCgkiQ29udGFjdEtleSI6ICIwMDM3RjAwMDAwejhWYnpRQUUiCiAgIH1dCn0.gnjf3FN7HMydDWUm-NMn3gaKpvuuXpEMrunR1A2PAgA",
"payloadType": "str",
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 110,
"y": 1000,
"wires": [
[
"30901b69.d485a4"
]
]
},
{
"id": "30901b69.d485a4",
"type": "http request",
"z": "f013e682.3118f8",
"name": "",
"method": "POST",
"ret": "txt",
"paytoqs": false,
"url": "http://localhost:1880/endpoints/demo/execute",
"tls": "",
"proxy": "",
"authType": "basic",
"x": 290,
"y": 1000,
"wires": [
[
"beca8ce7.95c0a"
]
]
},
{
"id": "739eaf33.de7e2",
"type": "template",
"z": "f013e682.3118f8",
"name": "Simple return",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "{ \"action\" : \"{{req.params.action}}\",\n \"status\" : \"OK\" \n}",
"output": "json",
"x": 580,
"y": 660,
"wires": [
[
"c5c130fa.e4b04"
]
]
},
{
"id": "954c450b.17ecc8",
"type": "comment",
"z": "f013e682.3118f8",
"name": "This can be used for testing",
"info": "",
"x": 160,
"y": 960,
"wires": []
},
{
"id": "8ab679d8.15e868",
"type": "comment",
"z": "f013e682.3118f8",
"name": "Static files (html, css, json)",
"info": "",
"x": 150,
"y": 420,
"wires": []
},
{
"id": "157cb491.436b7b",
"type": "http response",
"z": "f013e682.3118f8",
"name": "",
"statusCode": "",
"headers": {},
"x": 770,
"y": 780,
"wires": []
},
{
"id": "6fddb92b.d54758",
"type": "debug",
"z": "f013e682.3118f8",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 490,
"y": 900,
"wires": []
},
{
"id": "8bb75e68.fec1a",
"type": "comment",
"z": "f013e682.3118f8",
"name": "Actual action goes here - whatever it might be",
"info": "",
"x": 210,
"y": 880,
"wires": [],
"icon": "node-red/arrow-in.png"
},
{
"id": "b8f1eb7f.067bf8",
"type": "http response",
"z": "f013e682.3118f8",
"name": "html",
"statusCode": "",
"headers": {
"content-type": "text/html"
},
"x": 690,
"y": 500,
"wires": []
},
{
"id": "a0460c24.e8f65",
"type": "http in",
"z": "f013e682.3118f8",
"name": "/marketing-cloud/index.html",
"url": "/marketing-cloud/index.html",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 160,
"y": 500,
"wires": [
[
"e6a1e098.42916"
]
]
},
{
"id": "e6a1e098.42916",
"type": "template",
"z": "f013e682.3118f8",
"name": "static HTML",
"field": "payload",
"fieldType": "msg",
"format": "html",
"syntax": "plain",
"template": "<!DOCTYPE html>\n<html>\n <head>\n <title></title>\n <meta charset=\"utf-8\" />\n <meta http-equiv=\"x-ua-compatible\" content=\"ie=edge\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta http-equiv=\"Content-Security-Policy\" content=\"upgrade-insecure-requests\" />\n <script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js\"></script>\n <script type=\"text/javascript\" src=\"js/postmonger.js\"></script>\n <script type=\"text/javascript\">\n var mc_fuel_token = '';\n var connection = new Postmonger.Session();\n var payload = {};\n var steps = [{ label: 'Configure Postcard', key: 'step1' }];\n\n $(window).ready(onRender);\n\n connection.on('initActivity', initialize);\n connection.on('requestedTokens', onGetTokens);\n connection.on('requestedEndpoints', onGetEndpoints);\n connection.on('clickedNext', save);\n\n function onRender() {\n connection.trigger('ready');\n connection.trigger('requestTokens');\n connection.trigger('requestEndpoints');\n }\n\n function jsonCallback(data) {}\n\n function initialize(data) {\n if (data) {\n payload = data;\n }\n\n var hasInArguments = Boolean(\n payload['arguments'] &&\n payload['arguments'].execute &&\n payload['arguments'].execute.inArguments &&\n payload['arguments'].execute.inArguments.length > 0\n );\n\n if (hasInArguments && payload['arguments'].execute.inArguments[0].CampaignID) {\n $('#CampaignID').val(payload['arguments'].execute.inArguments[0].CampaignID);\n }\n\n connection.trigger('updateButton', {\n button: 'next',\n text: 'done',\n visible: true\n });\n }\n\n function onGetTokens(tokens) {\n if (tokens != null && tokens.fuel2token != null) {\n mc_fuel_token = tokens.fuel2token;\n }\n }\n\n function onGetEndpoints(endpoints) {}\n\n function save() {\n $('#errorMsgPreview').text('');\n\n var CampaignID = $('#CampaignID').val();\n var errMsg;\n\n var hasInArguments = Boolean(\n payload['arguments'] &&\n payload['arguments'].execute &&\n payload['arguments'].execute.inArguments &&\n payload['arguments'].execute.inArguments.length > 0\n );\n if (hasInArguments) {\n payload['arguments'].execute.inArguments[0].CampaignID = CampaignID;\n }\n\n if (CampaignID.length == 0) {\n errMsg = 'Error: Campaign ID cannot be blank.';\n console.error(errMsg);\n $('#errorMsgConfig').text(errMsg);\n connection.trigger('ready');\n } else {\n payload['metaData'].isConfigured = true;\n connection.trigger('updateActivity', payload);\n }\n }\n </script>\n <link rel=\"stylesheet\" type=\"text/css\" href=\"css/styles.css\" />\n </head>\n <body>\n <div id=\"step1\" class=\"step\">\n <div class=\"col-xs-9\">\n <h3>Campaign Association</h3>\n <div class=\"well\">\n <fieldset>\n <div>\n <font color=\"red\"><div id=\"errorMsgConfig\"></div></font>\n </div>\n <!-- TODO: Call back to Salesforce ?-->\n <div class=\"form-group\">\n <label for=\"cid\" class=\"label\">Campaign ID</label>\n <div class=\"col-lg-8\">\n <input type=\"text\" id=\"CampaignID\" />\n </div>\n </div>\n </fieldset>\n </div>\n </div>\n </div>\n </body>\n</html>\n",
"output": "str",
"x": 470,
"y": 500,
"wires": [
[
"b8f1eb7f.067bf8"
]
]
},
{
"id": "23a152b9.437fee",
"type": "http response",
"z": "f013e682.3118f8",
"name": "css",
"statusCode": "",
"headers": {
"content-type": "text/css"
},
"x": 690,
"y": 540,
"wires": []
},
{
"id": "b758f1b7.53d34",
"type": "http in",
"z": "f013e682.3118f8",
"name": "/marketing-cloud/css/style.css",
"url": "/marketing-cloud/css/style.css",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 170,
"y": 540,
"wires": [
[
"b4196642.0d04c8"
]
]
},
{
"id": "b4196642.0d04c8",
"type": "template",
"z": "f013e682.3118f8",
"name": "static CSS",
"field": "payload",
"fieldType": "msg",
"format": "css",
"syntax": "plain",
"template": "body {\n margin: 20px;\n padding: 0px;\n\tfont-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;\n\tfont-size:12px;\n}\n\nform {\n\twidth:400px;\n}\n\nselect\n{\n\tpadding: 5px;\n}\n\ntextarea, select, input{\n\twidth:400px;\n}\n\ndiv.isPush\n{\n\tpadding-bottom:10px;\n}\n\ninput[type='radio']\n{\n\twidth:20px;\n}\n\ninput[type='checkbox']\n{\n\twidth: 20px;\n\tborder:solid 1px red;\n}\n\ntd{\n\tvertical-align:top;\t\n}\n\ntd.label\n{\n\tpadding-top:2px;\n\twidth:120px;\n}\n\n#container {\n margin: 30px;\n}\n",
"output": "str",
"x": 470,
"y": 540,
"wires": [
[
"23a152b9.437fee"
]
]
},
{
"id": "268afbe1.895354",
"type": "http response",
"z": "f013e682.3118f8",
"name": "",
"statusCode": "",
"headers": {
"content-type": "text/javascript"
},
"x": 690,
"y": 580,
"wires": []
},
{
"id": "80b620de.65089",
"type": "http in",
"z": "f013e682.3118f8",
"name": "/marketing-cloud/js/postmonger.js",
"url": "/marketing-cloud/js/postmonger.js",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 180,
"y": 580,
"wires": [
[
"64b99f72.1a599"
]
]
},
{
"id": "64b99f72.1a599",
"type": "template",
"z": "f013e682.3118f8",
"name": "postmonger.js",
"field": "payload",
"fieldType": "msg",
"format": "javascript",
"syntax": "plain",
"template": "/*\n * Postmonger.js version 0.0.14\n * https://github.com/kevinparkerson/postmonger\n *\n * Copyright (c) 2012-2014 Kevin Parkerson\n * Available via the MIT or new BSD license.\n * Further details and documentation:\n * http://kevinparkerson.github.com/postmonger/\n *\n *///\n\n(function (root, factory) {\n\tif (typeof define === 'function' && define.amd) {\n\t\tdefine('postmonger', [], function () { return factory(root); });\n\t} else if (typeof exports === 'object') {\n\t\tmodule.exports = factory(root);\n\t} else {\n\t\t// OR use browser globals if AMD is not present\n\t\troot.Postmonger = factory(root);\n\t}\n}(this, function (root) {\n\troot = root || window;\n\n\tvar exports = exports || undefined;\n\tvar Postmonger;\n\tvar previous = root.Postmonger;\n\tvar _window = (root.addEventListener || root.attachEvent) ? root : window;\n\tvar Connection, Events, Session;\n\n\t//Set up Postmonger namespace, provide noConflict support, and version\n\tif (typeof(exports) !== 'undefined') {\n\t\tPostmonger = exports;\n\t} else {\n\t\tPostmonger = {};\n\t}\n\tPostmonger.noConflict = function () {\n\t\troot.Postmonger = previous;\n\t\treturn this;\n\t};\n\tPostmonger.version = '0.0.14';\n\n\t//Create a new Postmonger Connection\n\tConnection = Postmonger.Connection = function (options) {\n\t\toptions = (typeof(options) === 'object') ? options : {};\n\n\t\tvar connect = options.connect || _window.parent;\n\t\tvar from = options.from || '*';\n\t\tvar to = options.to || '*';\n\t\tvar self = this;\n\n\t\t//If string, grab based on id\n\t\tif (typeof(connect) === 'string') {\n\t\t\tconnect = document.getElementById(connect);\n\t\t}\n\n\t\t//If no connection, check for jquery object\n\t\tif (connect && !connect.postMessage && connect.jquery) {\n\t\t\tconnect = connect.get(0);\n\t\t}\n\n\t\t//If still no connection, check for iframe\n\t\tif (connect && !connect.postMessage && (connect.contentWindow || connect.contentDocument)) {\n\t\t\tconnect = connect.contentWindow || connect.contentDocument;\n\t\t}\n\n\t\t//Throw warning if connection could not be made\n\t\tif (!(connect && connect.postMessage)) {\n\t\t\tif (_window.console && _window.console.warn) {\n\t\t\t\t_window.console.warn(' Warning: Postmonger could not establish connection with ', options.connect);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tself.connect = connect;\n\t\tself.to = to;\n\t\tself.from = from;\n\n\t\treturn self;\n\t};\n\n\t//Postmonger.Events - Hacked together from Backbone.Events and two Underscore functions.\n\tEvents = Postmonger.Events = function () {\n\t\tvar eventSplitter = /\\s+/;\n\t\tvar self = this;\n\n\t\tself._callbacks = {};\n\n\t\tself._has = function (obj, key) {\n\t\t\treturn Object.prototype.hasOwnProperty.call(obj, key);\n\t\t};\n\n\t\tself._keys = function (obj) {\n\t\t\tif (Object.keys) {\n\t\t\t\treturn Object.keys(obj);\n\t\t\t}\n\n\t\t\tif (typeof(obj)!=='object') {\n\t\t\t\tthrow new TypeError('Invalid object');\n\t\t\t}\n\n\t\t\tvar keys = [];\n\n\t\t\tfor (var key in obj) {\n\t\t\t\tif (self._has(obj, key)) {\n\t\t\t\t\tkeys[keys.length] = key;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn keys;\n\t\t};\n\n\t\tself.on = function (events, callback, context) {\n\t\t\tvar calls, event, node, tail, list;\n\n\t\t\tif (!callback) {\n\t\t\t\treturn self;\n\t\t\t}\n\n\t\t\tevents = events.split(eventSplitter);\n\n\t\t\tself._callbacks = self._callbacks || {};\n\t\t\tcalls = self._callbacks;\n\n\t\t\twhile (event = events.shift()) {\n\t\t\t\tlist = calls[event];\n\n\t\t\t\tnode = (list) ? list.tail : {};\n\t\t\t\ttail = {};\n\n\t\t\t\tnode.next = tail;\n\t\t\t\tnode.context = context;\n\t\t\t\tnode.callback = callback;\n\n\t\t\t\tcalls[event] = {\n\t\t\t\t\ttail: tail,\n\t\t\t\t\tnext: (list) ? list.next : node\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn self;\n\t\t};\n\n\t\tself.off = function (events, callback, context) {\n\t\t\tvar calls = self._callbacks;\n\t\t\tvar event, node, tail, cb, ctx;\n\n\t\t\tif (!calls) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!(events || callback || context)) {\n\t\t\t\tdelete self._callbacks;\n\t\t\t\treturn self;\n\t\t\t}\n\n\t\t\tevents = (events) ? events.split(eventSplitter) : self._keys(calls);\n\n\t\t\twhile (event = events.shift()) {\n\t\t\t\tnode = calls[event];\n\t\t\t\tdelete calls[event];\n\t\t\t\tif (!node || !(callback || context)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttail = node.tail;\n\t\t\t\twhile ((node = node.next) !== tail) {\n\t\t\t\t\tcb = node.callback;\n\t\t\t\t\tctx = node.context;\n\t\t\t\t\tif (((callback && cb) !== callback) || ((context && ctx) !== context)) {\n\t\t\t\t\t\tself.on(event, cb, ctx);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn self;\n\t\t};\n\n\t\tself.trigger = function (events) {\n\t\t\tvar event, node, calls, tail, args, all, rest;\n\n\t\t\tif (!(calls = self._callbacks)) {\n\t\t\t\treturn self;\n\t\t\t}\n\n\t\t\tall = calls.all;\n\t\t\tevents = events.split(eventSplitter);\n\t\t\trest = Array.prototype.slice.call(arguments, 1);\n\n\t\t\twhile (event = events.shift()) {\n\t\t\t\tif (node = calls[event]) {\n\t\t\t\t\ttail = node.tail;\n\t\t\t\t\twhile ((node = node.next) !== tail) {\n\t\t\t\t\t\tnode.callback.apply(node.context || self, rest);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (node = all) {\n\t\t\t\t\ttail = node.tail;\n\t\t\t\t\targs = [event].concat(rest);\n\t\t\t\t\twhile ((node = node.next) !== tail) {\n\t\t\t\t\t\tnode.callback.apply(node.context || self, args);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn self;\n\t\t};\n\n\t\treturn self;\n\t};\n\n\t//Create a new Postmonger Session\n\tSession = Postmonger.Session = function () {\n\t\tvar args = (arguments.length>0) ? Array.prototype.slice.call(arguments, 0) : [{}];\n\t\tvar connections = [];\n\t\tvar incoming = new Events();\n\t\tvar outgoing = new Events();\n\t\tvar self = this;\n\t\tvar connection, i, j, l, ln, postMessageListener;\n\n\t\t//Session API hooks\n\t\tself.on = incoming.on;\n\t\tself.off = incoming.off;\n\t\tself.trigger = outgoing.trigger;\n\t\tself.end = function () {\n\t\t\tincoming.off();\n\t\t\toutgoing.off();\n\t\t\tif (_window.removeEventListener) {\n\t\t\t\t_window.removeEventListener('message', postMessageListener, false);\n\t\t\t} else if (_window.detachEvent) {\n\t\t\t\t_window.detachEvent('onmessage', postMessageListener);\n\t\t\t}\n\t\t\treturn self;\n\t\t};\n\n\t\t//Establishing connections\n\t\tfor (i=0, l=args.length; i<l; i++) {\n\t\t\tconnection = new Connection(args[i]);\n\t\t\tif (connection) {\n\t\t\t\tfor (j=0, ln=connections.length; j<ln; j++) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tconnections[j].connect === connection.connect &&\n\t\t\t\t\t\tconnections[j].from === connection.from &&\n\t\t\t\t\t\tconnections[j].to === connection.to\n\t\t\t\t\t) {\n\t\t\t\t\t\tconnection = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (connection) {\n\t\t\t\t\tconnections.push(connection);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//Listener for incoming messages\n\t\tpostMessageListener = function(event){\n\t\t\tvar conn = null;\n\t\t\tvar message = [];\n\t\t\tvar data;\n\t\t\tvar k, len;\n\n\t\t\t//Attempt to find the connection we're dealing with\n\t\t\tfor (k=0, len=connections.length; k<len; k++) {\n\t\t\t\tif (connections[k].connect === event.source) {\n\t\t\t\t\tconn = connections[k];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Check if we've found the connection\n\t\t\tif (!conn) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t//Check if the message is from the expected origin\n\t\t\tif (conn.from !== '*' && conn.from !== event.origin) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t//Check the data that's been passed\n\t\t\ttry{\n\t\t\t\tdata = JSON.parse(event.data);\n\t\t\t\tif(!data.e){\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}catch(e){\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t//Format the passed in data\n\t\t\tmessage.push(data.e);\n\t\t\tdelete data.e;\n\t\t\tfor (k in data) {\n\t\t\t\tmessage.push(data[k]);\n\t\t\t}\n\n\t\t\t//Send the message\n\t\t\tincoming['trigger'].apply(root, message);\n\t\t};\n\n\t\t//Add the listener\n\t\tif (_window.addEventListener) {\n\t\t\t_window.addEventListener('message', postMessageListener, false);\n\t\t} else if(_window.attachEvent) {\n\t\t\t_window.attachEvent('onmessage', postMessageListener);\n\t\t} else{\n\t\t\tif (_window.console && _window.console.warn) {\n\t\t\t\t_window.console.warn('WARNING: Postmonger could not listen for messages on window %o', _window);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t//Sending outgoing messages\n\t\toutgoing.on('all', function () {\n\t\t\tvar args = Array.prototype.slice.call(arguments, 0);\n\t\t\tvar message = {};\n\t\t\tvar k, len;\n\n\t\t\tmessage.e = args[0];\n\n\t\t\tfor (k=1, len=args.length; k<len; k++) {\n\t\t\t\tmessage['a' + k] = args[k];\n\t\t\t}\n\n\t\t\tfor (k=0, len=connections.length; k<len; k++) {\n\t\t\t\tconnections[k].connect.postMessage(JSON.stringify(message), connections[k].to);\n\t\t\t}\n\t\t});\n\n\t\treturn self;\n\t};\n\n\treturn Postmonger;\n}));",
"output": "str",
"x": 480,
"y": 580,
"wires": [
[
"268afbe1.895354"
]
]
},
{
"id": "3eb29099.23cbb",
"type": "http in",
"z": "f013e682.3118f8",
"name": "/marketing-cloud",
"url": "/marketing-cloud",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 120,
"y": 460,
"wires": [
[
"e6a1e098.42916"
]
]
},
{
"id": "e62252d8.6eaae",
"type": "catch",
"z": "f013e682.3118f8",
"name": "Catch JWT Error",
"scope": [
"32b72ce.89070d4"
],
"uncaught": false,
"x": 320,
"y": 820,
"wires": [
[
"de462a32.264b48"
]
]
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment