10 Ideas to implement in SFMC

HEADER image

I have been using Salesforce Marketing cloud for some time now. It’s a powerful tool and a lot can be accomplished. Having said that I have also noticed that we can take it to the next level through a few process implementations. Not too complex but do they require some preparation. In this blog, I am trying to share my lessons learned.

Full Disclaimer: I haven’t implemented all of them.

My hope is someone might get some inspiration and take them forward!

1.Error Handling:

It gets difficult to understand where the error is occurring when you have hundreds of scripts in automation studio and cloud pages. Debugging an issue can be a daunting task.

For all server-side scripting functions, we can have a simple construct where we use a data extension for error logging.

In the below code snippet I have used a data extension named Global_Error_Log.From a try-catch block we populate the data extension, I added a small error description, current time, function name as meaningful information.

Code Snippet:

Platform.Load("core","1").                                                  //This is a global DE which should be used in the catch block            var de=DataExtension.Init('Global_Error_Log');                        try{}                                                                   catch(ex)                                                              {                                                                       de.Rows.Add(ErrorDescription:Stringify(ex)};                            }                 

2.Customize Send Logs

Each marketing cloud instance comes with a default DE for email send and SMS send. All email and SMS send are logged in this DE automatically. That’s great but we can do better. We can create custom fields in this DE and in the email or SMS send use AMPScript and use a variable with the same name. If we populate this variable during send, the field in the DE will also get populated.

Let’s say we have a user_id that we are populating from the CRM system. We can create a data attribute in the send log DE for the user_id and use an AMPScript variable during the email or SMS sent to populate that. This feature is really helpful when we have to do custom reporting based on subscribers.

3.Retrieve Data Extension definition

The use case for this functionality would apply to scenarios where we would like to create a large no of data extensions on the fly. We would like to iterate through all the data extensions in a marketing cloud instance and then retrieve the details of the individual functions something in similar lines below.

To retrieve all the Data Extensions from a BU, You cannot use the  REST API and you have to go to SOAP. We can use an API client like Postman or download SDK for marketing cloud and use a language like Python.

var birthdayDE = DataExtension.Init("birthdayDE");
var fields = birthdayDE.Fields.Retrieve();

We can save the name of the data extension and the resulting field JSON in a target data extension and that becomes a crude DB backup.

4.Server-side JavaScript to create DE

This is an extension of point#3 where we use a data extension which contains all the DE name and the corresponding JSON. We iterate through the DE and create the Data Extension in a particular BU.

Code snippet:

The first code snippet creates a field in a data extension. We initialize the data extension and then create a new field through de.Fields.add functions.

The second code snippet creates the whole data extension and we put the JSON under the deObj at a single go.

var de = DataExtension.Init('SSJSTest');

var newField = {
  Name : "NewFieldV2",
  CustomerKey : "CustomerKey",
  FieldType : "Number",
  IsRequired: true,
  DefaultValue: "100"
var status = de.Fields.Add(newField);

var deObj={
"Name":"Slalom_Rocks", SendableInfo:{ Field:{"Name":"Read_Your_Value","FieldType":"Text"}, RelatesOn:"Subscriber Key"}, "IsTestable":true, "Fields":[ {"Name":"FieldName","FieldType":"Number","IsPrimaryKey":true}, {"Name":"FirstName","FieldType":"Text","MaxLength":50}, ] }; var myDE=DataExtension.Add(deObj)

5.Copy all Journeys into JSON for migration

The Journeys are exposed through REST API.
We can Get the journey detail through the following GET REST call.
From the resulting JSON get the detail of a specific journey.
Create that journey with the following  POST API call.
Now use the JSON to create a journey in a new BU.

6. Use Content builder API

In SFMC a folder, image, email are content. Content builder can be used to upload these contents.SFMC also comes with a powerful API. With any REST client, we can use the API to do an advanced search or do repetitive tasks.

Example use case:

There are thousands of content and you are trying to search for something specific.

Gets an asset collection by advanced query.

The following is a code snippet from Salesforce marketing cloud documentation.

Host: https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com
POST //asset/v1/content/assets/query
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN



        { "property":"id", "direction":"ASC" }


7. Use validate function of Automation Studio

Validate function can check Data Extensions for specific conditions and trigger emails. Let’s say there is critical automation that runs every night and typically it processes a million record. You want to stop the processing if the source DE has less than 100K record and also want to alert the System Admin. Validate function is the perfect candidate for this.

It checks the current record count of a specified data extension: If the record count falls outside a defined range, the activity sends an email notification, stops the automation, or both.

Automation Studio Verification

8.Enhanced Dynamic Content

Enhanced Dynamic Content lets you import into Content Builder a delimited file containing text and image URLs to create enhanced dynamic content for emails.

Instead of using AMPscript and data extensions to manually create complex dynamic content and the rules for each variation, the system creates the content from the data in your import file. Content Builder saves the assets as Enhanced Dynamic Content Maps in the content library that you can use as blocks in emails and templates. You can link your enhanced dynamic content to an audience during the import or while adding the blocks to an email or template.
Once we figure out which areas of email will change over time and based on what criteria the file can be structured pretty quickly.
This gives back control to the marketer to control the content and not depend on IT.
Let’s say the discount code changes based on the type of holiday. We can create a file mapping for it.
In case of last-minute data change requests no need to change the verified email. We only change our data file.

9.Learn to create Journey Builder custom Activity

The activities we drag into Journey builder are not limited by what we can drag onto the canvas. We can define our own activities. This is a powerful feature. Having said that we probably will need this very few times in our implementation.

If we are integrating with external systems for data updates based on user journeys this would be useful.

Use case: every time an email is sent to customer and he has not opened it in 7 days , I want to send direct mail. The direct email will be an integration with UPS and it will take customer’s current address as an input.

We can create a canvas activity for postal send. A marketer can use this as a drag and drop and visualize the whole customer journey.

Prerequisites :

Access to a hosting platform like Heroku.

Understanding of JavaScript and web architecture.

10.Create Dynamic Queries from server-side Javascript

For complex scenarios where audience segmentation is dynamic, we can create dynamic queries leveraging the query object.

I have put two code snippets as an example.

The first code snippet concatenates a string and prepares the query text. It initiates a query object.

The second function takes a query string and a query object and executes it.

function CreateDynamicQuery(){

var outreachGroupDE = DataExtension.Init(“Emp_Group_DE”);
var groupData = outreachGroupDE.Rows.Retrieve();

for (var i = 0; i < groupData.length; i++)

if(i < groupData.length-1)
groupList = groupList.concat(“,”);

var qd=QueryDefinition.Init(‘ Select_Group_By_Practice_Key’);
var queryName = “USE_DE”;
var query = “SELECT GroupName, PracticeName,LocalOffice,Role,”+ groupData[i].GroupName +”as GroupName from Emp_Info “;
query=query+ “WHERE PracticeName IN(‘”;

status = queryUpdatePerform(qd,queryName,query);

function queryUpdatePerform(qd,querytext,query)
var update_status = qd.Update({
Name : querytext,
QueryText: query
var perform_status = qd.Perform();
status = “{Update:”.concat(update_status).concat(“, “).concat(“Perform:”).concat(query).concat(“}”);
return status;