Installed Package Types
Internationalize Events
Create Unique Journey Results using Transaction Keys
Example Contact Event
List Your App in AppExchange
1{
2 "workflowApiVersion": "1.1",
3 "metaData": {
4 "icon": "images/icon.png",
5 "transactionKeys": {
6 "0": {
7 "from": "Event Property",
8 "to": "DE_Name.DE_Property"
9 }
10 }
11 },
12 "type": "Event",
13 "lang": {
14 "en-US": {
15 "name": "Event (Workflow API v1.1)",
16 "description": "An example event using workflow API v1.1 format.",
17 "selectCountry": "Select Country",
18 "enterFirstName": "Enter First Name",
19 "enterLastName": "Enter Last Name",
20 "enterFavoriteFood": "Enter Favorite Food",
21 "countryCodeLabel": "Country Code",
22 "firstNameLabel": "First Name",
23 "lastNameLabel": "Last Name",
24 "favoriteFoodLabel": "Favorite Food",
25 "selectTransactionKeyMapping": "Transaction Key"
26 }
27 },
28 "configurationArguments": {},
29 "filterExpressionEnabled": false,
30 "wizardSteps": [
31 { "key": "selectCountry", "label": "selectCountry" },
32 { "key": "enterFirstName", "label": "enterFirstName" },
33 { "key": "enterLastName", "label": "enterLastName" },
34 {
35 "key": "enterFavoriteFood",
36 "label": "enterFavoriteFood",
37 "active": false
38 },
39 {
40 "key": "selectTransactionKeyMapping",
41 "label": "selectTransactionKeyMapping"
42 }
43 ],
44 "userInterfaces": {
45 "configModal": {
46 "url": "index.html"
47 },
48 "summary": [
49 {
50 "valuePath": "arguments.countryCode",
51 "label": "countryCodeLabel"
52 },
53 {
54 "valuePath": "arguments.firstName",
55 "label": "firstNameLabel"
56 },
57 {
58 "valuePath": "arguments.lastName",
59 "label": "lastNameLabel"
60 },
61 {
62 "valuePath": "arguments.favoriteFood",
63 "label": "favoriteFoodLabel"
64 },
65 {
66 "valuePath": "metaData.transactionKeys",
67 "label": "Transaction Key"
68 }
69 ]
70 }
71}Every custom event must have an index.html in the root of its endpoint.
1<!DOCTYPE html>
2
3<html lang="en">
4 <head>
5 <meta charset="utf-8" />
6 <title>Custom Event Test</title>
7
8 <script type="text/javascript" src="js/jquery.min.js"></script>
9 <script type="text/javascript" src="js/require.js"></script>
10 <script type="text/javascript">
11 (function () {
12 var config = {
13 baseUrl: "",
14 };
15
16 var dependencies = ["customEvent"];
17
18 require(config, dependencies);
19 })();
20 </script>
21
22 <!--Styles-->
23 <style type="text/css">
24 body {
25 padding: 15px;
26 margin: 0;
27 }
28 h1 {
29 font-size: 16px;
30 }
31 .step {
32 display: none;
33 }
34 #step1 {
35 display: block;
36 }
37 </style>
38 </head>
39 <body>
40 <div id="step1" class="step">
41 <h1>Step 1: Country Code</h1>
42 <select id="select-country-code">
43 <option value="US">United States</option>
44 <option value="GB">United Kingdom</option>
45 <option value="BR">Brazil</option>
46 <option value="DE">Germany</option>
47 </select>
48 <br />
49 <button id="toggleLastStep">Toggle Favorite Food Step</button>
50 </div>
51 <div id="step2" class="step">
52 <h1>Step 2: First Name</h1>
53 <input id="select-first-name" />
54 </div>
55 <div id="step3" class="step">
56 <h1>Step 3: Last Name</h1>
57 <input id="select-last-name" />
58 </div>
59 <div id="step4" class="step">
60 <h1>Step 4: Favorite Food</h1>
61 <input id="select-favorite-food" />
62 </div>
63 </body>
64</html>Postmonger is required for communication between Journey Builder and the custom event.
1define(["js/postmonger"], function (Postmonger) {
2 "use strict";
3
4 var connection = new Postmonger.Session();
5 var payload = {};
6 var lastStepEnabled = false;
7 var steps = [
8 // initialize to the same value as what's set in config.json for consistency
9 { key: "selectCountry", label: "selectCountry" },
10 { key: "enterFirstName", label: "enterFirstName" },
11 { key: "enterLastName", label: "enterLastName" },
12 { key: "enterFavoriteFood", label: "enterFavoriteFood", active: false },
13 ];
14 var currentStep = steps[0].key;
15
16 $(window).ready(onRender);
17
18 connection.on("initEvent", initialize);
19 connection.on("requestedTokens", onGetTokens);
20 connection.on("requestedEndpoints", onGetEndpoints);
21
22 connection.on("clickedNext", onClickedNext);
23 connection.on("clickedBack", onClickedBack);
24 connection.on("gotoStep", onGotoStep);
25
26 function initialize(data) {
27 var countryCode;
28 var firstName;
29 var lastName;
30
31 if (data) {
32 payload = data;
33 }
34
35 if (payload["arguments"]) {
36 countryCode = payload["arguments"].countryCode;
37 firstName = payload["arguments"].firstName;
38 lastName = payload["arguments"].lastName;
39 }
40
41 $("#select-country-code").val(countryCode);
42 $("#select-first-name").val(firstName);
43 $("#select-last-name").val(lastName);
44 }
45
46 function onGetTokens(tokens) {
47 // Response: tokens = { token: <legacy token>, fuel2token: <fuel api token> }
48 // console.log(tokens);
49 }
50
51 function onGetEndpoints(endpoints) {
52 // Response: endpoints = { restHost: <url> } i.e. "rest.s1.qa1.exacttarget.com"
53 // console.log(endpoints);
54 }
55
56 function onClickedNext() {
57 if (
58 (currentStep.key === "enterLastName" && steps[3].active === false) ||
59 currentStep.key === "enterFavoriteFood"
60 ) {
61 save();
62 } else {
63 connection.trigger("nextStep");
64 }
65 }
66
67 function onClickedBack() {
68 connection.trigger("prevStep");
69 }
70
71 function onGotoStep(step) {
72 showStep(step);
73 connection.trigger("ready");
74 }
75
76 function onRender() {
77 connection.trigger("ready"); // JB will respond the first time 'ready' is called with 'initEvent'
78
79 connection.trigger("requestTokens");
80 connection.trigger("requestEndpoints");
81
82 $("#toggleLastStep").click(function () {
83 lastStepEnabled = !lastStepEnabled; // toggle status
84 steps[3].active = !steps[3].active; // toggle active
85
86 connection.trigger("updateSteps", steps);
87 });
88 }
89
90 function showStep(step, stepIndex) {
91 if (stepIndex && !step) {
92 step = steps[stepIndex - 1];
93 }
94
95 currentStep = step;
96
97 $(".step").hide();
98
99 switch (currentStep.key) {
100 case "selectCountry":
101 $("#step1").show();
102 break;
103 case "enterFirstName":
104 $("#step2").show();
105 $("#step2 input").focus();
106 break;
107 case "enterLastName":
108 $("#step3").show();
109 $("#step3 input").focus();
110 break;
111 case "enterFavoriteFood":
112 $("#step4").show();
113 $("#step4 input").focus();
114 break;
115 }
116 }
117
118 function save() {
119 var countryCode = $("#select-country-code")
120 .find("option:selected")
121 .attr("value");
122 var firstName = $("#select-first-name").val();
123 var lastName = $("#select-last-name").val();
124 var favoriteFood = $("#select-favorite-food").val();
125
126 payload["arguments"] = payload["arguments"] || {};
127 payload["arguments"].countryCode = countryCode;
128 payload["arguments"].firstName = firstName;
129 payload["arguments"].lastName = lastName;
130
131 // Example criteria - if 'filterExpressionEnabled' is set to true in config.json, Journey Builder will
132 // populate this step with the 'criteria' XML passed here
133 // payload['arguments'].criteria = "<FilterDefinition Source='SubscriberAttribute'><ConditionSet Operator='AND' ConditionSetName='Grouping'><Condition ID='13D65BB5-1F98-E411-9D68-00237D5401CE' isParam='false' Operator='Equal' operatorEditable='0' valueEditable='1' annotation=''><Value><![CDATA[" + countryCode + "]]></Value></Condition><Condition ID='0CD65BB5-1F98-E411-9D68-00237D5401CE' isParam='false' Operator='Equal' operatorEditable='0' valueEditable='1' annotation=''><Value><![CDATA[" + firstName + "]]></Value></Condition><Condition ID='12D65BB5-1F98-E411-9D68-00237D5401CE' isParam='false' Operator='Equal' operatorEditable='0' valueEditable='1' annotation=''><Value><![CDATA[" + lastName + "]]></Value></Condition></ConditionSet></FilterDefinition>";
134
135 if (favoriteFood && steps[3].active) {
136 payload["arguments"].favoriteFood = favoriteFood;
137 }
138
139 payload["metaData"] = payload["metaData"] || {};
140
141 payload["configurationArguments"] = payload["configurationArguments"] || {};
142
143 payload.dataExtensionId = "<data extension ID>";
144
145 connection.trigger("updateEvent", payload);
146 }
147});