Using Entry Source Data in Journey Builder Custom Activities

Journey Builder Custom Activities for Salesforce Marketing Cloud enable you to extend the platform capabilities by creating highly configurable interfaces which call externally-hosted endpoints when a Contact arrives at a custom activity in a published Journey.

There are several dependencies required by custom activities, which include Postmonger — a lightweight messaging Javascript utility for cross-domain messaging that is used to send data and event related information between Journey Builder and a custom activity interface, when a user configures a custom activity.

Use Cases

The available Postmonger methods and events are provided on developer.salesforce.com, however a common use case for custom activities is to retrieve Data Extension fields from the Journey Entry Source. For example, you might want to include a dropdown menu in your custom activity interface so a user can select a specific entry source field, then when the Journey is published, the field value for the Contact is included in the payload to the externally hosted ‘execute’ endpoint. Or, perhaps you want to retrieve the entire schema of the entry source, then include these field values (i.e. Journey Data) when the execute endpoint is called.

Custom Activities include the ability to define field values from the Data Source through support of Data Binding in the Event Context, which comprise of mustache formatted strings in the activity’s config.json file (a definition file that is loaded when the custom activity interface is opened). However, it’s generally not practical to define Entry Source fields in the config.json file, as these values will change between Journeys. Specifically, the format requires the assigned entry event key (a UUID value) along with the field name in the following format:

{{Event.entry-event-key.field-name}}

As a solution for these use cases, there are two undocumented Postmonger calls which enable the entry source schema to be retrieved, which can then be used by the custom activity interface, and/or programatically added as inArguments to to include defined key/value pairs when the execute endpoint is called.

Retrieving the Entry Source Schema

The connection.trigger Postmonger method can be used to retrieve the Entry Source schema as follows:

connection.trigger('requestSchema');

This returns the entire Data Extension schema of the Journey Entry Source, for example:

[
   {
      "key":"Event.APIEvent-1a11c19c-7952-488a-99d7-069fa2bc543c.Id",
      "type":"Text",
      "length":18,
      "default":null,
      "isNullable":null,
      "isPrimaryKey":null
   },
   {
      "key":"Event.APIEvent-1a11c19c-7952-488a-99d7-069fa2bc543c.FirstName",
      "type":"Text",
      "length":40,
      "default":null,
      "isNullable":null,
      "isPrimaryKey":null
   },
   {
      "key":"Event.APIEvent-1a11c19c-7952-488a-99d7-069fa2bc543c.LastName",
      "type":"Text",
      "length":80,
      "default":null,
      "isNullable":null,
      "isPrimaryKey":null
   }
]

In turn, the schema can then be evaluated by listening for the requestedSchema event using the connection.on method:

connection.on('requestedSchema', function (data) { /* do something */ });

Entry Source fields for Execute Call

The following example demonstrates how Postmonger can be used to retrieve the Entry Source schema and push the fields as inArguments, so the field values (i.e. Journey Data) are included in the payload sent to the execute endpoint when a Contact arrives at the custom activity in a published journey:

var connection = new Postmonger.Session();
var payload = {};

$(window).ready(onRender);

connection.on('initActivity', initialize);
connection.on('clickedNext', save);

function onRender() {
  connection.trigger('ready');
}

function initialize(data) {

  if (data) {
    payload = data;
  }

  connection.trigger('requestSchema');
  connection.on('requestedSchema', function (data) {

    // add entry source attributes as inArgs
    const schema = data['schema'];

    for (var i = 0, l = schema.length; i < l; i++) {
        var inArg = {};
        let attr = schema[i].key;
        let keyIndex = attr.lastIndexOf('.') + 1;
        inArg[attr.substring(keyIndex)] = '{{' + attr + '}}';
        payload['arguments'].execute.inArguments.push(inArg);
    }
  });

  let argArr = payload['arguments'].execute.inArguments;

}

function save() {

  /* the following code is optional, but provides an example of 
     how to append additional key/value pair(s) as inArguments, 
     for example, a form field value from the custom activity html

  var fieldVal = document.getElementById('your-field-id').value;
  var keyObj = { InsertKeyName: fieldVal };
  payload['arguments'].execute.inArguments.push(keyObj);

  */

  payload.metaData.isConfigured = true;
  connection.trigger('updateActivity', payload);

}

The for loop in this code programatically builds an array of entry source data as key/value pairs in the required data binding syntax, for example:

[
   {
      "Id":"{{Event.APIEvent-1a11c19c-7952-488a-99d7-069fa2bc543c.Id}}"
   },
   {
      "FirstName":"{{Event.APIEvent-1a11c19c-7952-488a-99d7-069fa2bc543c.FirstName}}"
   },
   {
      "LastName":"{{Event.APIEvent-1a11c19c-7952-488a-99d7-069fa2bc543c.LastName}}"
   }
]

The connection.trigger method (on the last line) updates the custom activity with these key/value pairs so they can be used as inArguments for the execute endpoint (as an alternative to hardcoding the key/value pairs in config.json).

Including Entry Source fields in a form field

The following example indicates how to retrieve the entry source schema, then display field values in the custom activity interface:

var connection = new Postmonger.Session();
var payload = {};

$(window).ready(onRender);

connection.on('initActivity', initialize);
connection.on('clickedNext', onClickedNext);

function onRender() {

    connection.trigger('ready');

    $('#select1').change(function() {
        var name = $('#select1').find('option:selected').html();
        console.log('PNR Field selected : ', name);
    });
}

function initialize(data) {
    $('#step1').show();
    if (data) {
        payload = data;
    }

    connection.trigger('requestSchema');
    connection.on('requestedSchema', function(data) {
        const schema = data['schema'];

        for (var i = 0, l = schema.length; i < l; i++) {
            let attr = schema[i].key;

            // populate select dropdown 
            let option = $('<option></option>')
                .attr('id', schema[i].key)
                .text(schema[i].name);

            $('#idField').append(option);

        }
    });
}

function onClickedNext() {
    var idField = $('#idField').find('option:selected').html();
    payload['arguments'].execute.inArguments.push({
        idField: idField
    })
    payload['metaData'].isConfigured = true;
    connection.trigger('updateActivity', payload);
}

The for loop creates option tags which are appended to an empty select tag in the html file. The following code can then be included in the index.html file (which is used to render the custom activity interface).

  <select class="slds-select" id="idField"></select>

When the user has finished configuring the activity (by clicking the Next button). the connection.trigger method (on the last line) updates the custom activity with the selected field as an inArgument (using idField as the key), so the corresponding field value will be sent to the execute endpoint when a Contact reaches the activity in a published journey.

Summary

Journey Builder Custom Activities extend the customer journey management and integration capabilities of the platform. The additional ability to retrieve Journey Entry Source fields and display them in a custom activity or include field values in a payload to an execute endpoint is an invaluable feature, as it unlocks many data integration use cases.


Want to do more with Journey Builder and learn how to improve the integration capabilities of your own Marketing Cloud platform? Get in touch! We’d love to discuss how you can customize your Salesforce Marketing Cloud to deliver the best possible experience for your clients and maximize the ROI for your organization.

You may be interested in

The Three Pillars of Marketing Attribution

Marketing Attribution has been a controversial topic among marketers. There are two sides in this debate: One side believes the attribution data collected today shouldn’t be taken too seriously, as we only capture the information provided to us at the point of conversion. The other side believes it is better to measure what’s available rather […]

Read More

Integrating Financial Services Cloud and Data Cloud

The Customer Data Problem The vast majority of Financial Services organizations today share a common problem: customer data is siloed across departments and systems. Imagine an investment firm that offers a portfolio of financial products like mutual funds, stocks and retirement planning services. Information about these various products typically reside in separate (and typically proprietary) […]

Read More

Sign up for the latest tips & news from CloudKettle

Thank you for subscribing.