A guide to monitor SFMC Automations

  • By Arusha Shahi

Have you ever had a critical automation paused, only to find out 24 hours later? In Salesforce Marketing Cloud, keeping an eye on dozens of automations can be a full-time job. To solve this, I built a custom Automation Monitoring System. Here are the 4 steps I took to move from manual checking to automated alerts.

Automation activity

Step 1: Building Data Extensions

First, I needed a place to store the "Truth." I created two Data Extensions:

Automation_Monitoring_Log:

My master list. It contains the ExternalKey of every automation I want to watch, a Flag to turn monitoring on/off, and a Status field to check if the automation is paused. I added critical automations manually in this table.

Paused_Automation_Log:

This table only gets filled via SQL activity if the system finds a paused automation.

Data Extension

Step 2: The "Translator" Script (SSJS)

The heart of this system is a SSJS activity. Since SFMC speaks in "Status Codes" (like 4 for Paused or -1 for Error), I wrote a script to:

  • Loop through my monitored list.
  • Request the current status of each automation via the API.
  • Translate those numbers into words like "Paused" or "Scheduled."
  • Update my Data Extension with the latest info.

This step turns raw system data into actionable information.


<script runat="server">

Platform.Load("Core","1.1.1");
    
var i;  
// Look for rows where Flag is 'True'
var dataRows = Platform.Function.LookupRows('Automation_Monitoring_Log','Flag','True'); 

if(dataRows && dataRows.length > 0) {

    for(i=0; i<dataRows.length; i++) {
        
        var automationCustomerKey = dataRows[i]["ExternalKey"];

        // Setup the request to the system
        var rr = Platform.Function.CreateObject("RetrieveRequest");
        Platform.Function.SetObjectProperty(rr, "ObjectType", "Automation");
        Platform.Function.AddObjectArrayItem(rr, "Properties", "CustomerKey");
        Platform.Function.AddObjectArrayItem(rr, "Properties", "Name");
        Platform.Function.AddObjectArrayItem(rr, "Properties", "Status");
        Platform.Function.AddObjectArrayItem(rr, "Properties", "ScheduledTime");     

        // Filter for the specific key
        var sfp = Platform.Function.CreateObject("SimpleFilterPart");
        Platform.Function.SetObjectProperty(sfp, "Property", "CustomerKey");
        Platform.Function.SetObjectProperty(sfp, "SimpleOperator", "equals");
        Platform.Function.AddObjectArrayItem(sfp, "Value", automationCustomerKey);
        Platform.Function.SetObjectProperty(rr, "Filter", sfp);

        var retrieveStatus = [0,0,0];
        var automationResultSet = Platform.Function.InvokeRetrieve(rr, retrieveStatus);

        // Make sure the system actually gave us a result back
        if (automationResultSet != null && automationResultSet.length > 0) {
            
            var Name = automationResultSet[0]["Name"];
            var Status = automationResultSet[0]["Status"];
            var ScheduledTime = automationResultSet[0]["ScheduledTime"];
            var Print = ""; // Initialize the word bucket

            // Translate the numbers to words
            if (Status == "-1") { Print = 'Error'; }
            else if (Status == "0") { Print = 'BuildingError'; }
            else if (Status == "1") { Print = 'Building'; }
            else if (Status == "2") { Print = 'Ready'; }
            else if (Status == "3") { Print = 'Running'; }
            else if (Status == "4") { Print = 'Paused'; }
            else if (Status == "5") { Print = 'Stopped'; }
            else if (Status == "6") { Print = 'Scheduled'; }
            else if (Status == "7") { Print = 'Awaiting Trigger'; }
            else { Print = 'InactiveTrigger'; }

            // Save the data back to your table
            Platform.Function.UpsertData(
                "Automation_Monitoring_Log", 
                ["ExternalKey"], [automationCustomerKey], 
                ["AutomationName", "Status", "ScheduledTime"], [Name, Print, ScheduledTime]
            ); 
        }
    }
}
      
</script>

Step 3: Verification Activity

I didn't want to receive a "System is fine" email every single day. I only wanted to know when things were broken. To do this, I added a Verification Activity:

I set a rule: If the Paused Log has 0 rows, STOP the automation. This ensures I only get an email if there's actually a "Paused" automation found by my script.

Verification

Step 4: The Dynamic Alert (AMPscript & HTML)

Finally, I designed a clean, professional email. Using AMPscript, the email "reaches into" the Paused Log and builds a dynamic table.

If three automations are paused, the email shows a 3-row table with the names and keys of exactly what needs fixing. It's simple, professional, and saves me hours of manual troubleshooting.

Email

The Result

By combining SSJS, SQL, and AMPscript, I've created a automation monitoring system. It doesn't just tell me there's a problem; it tells me exactly where the problem is, so I can fix it before the morning coffee is cold.

Are you building custom tools in SFMC? Let's connect and share ideas!