🔥 500+ people already subscribed. Why not you? Get the monthly newsletter with handy code snippets, tips, and marketing automation insights.

background shape
background shape

How to Create a Custom Workflow Activity in Adobe Campaign Classic

Adobe Campaign Classic offers a powerful set of workflow activities out of the box – from data queries to email deliveries. But what if your business logic requires something Adobe didn’t anticipate? That’s where custom workflow activities come into play.

Custom activities allow developers to extend the platform with their own logic – whether it’s calling external APIs, integrating with tools like Slack or Discord, implementing complex data operations, or even adding a custom push notification service. These activities behave like any native activity, appearing in the workflow palette with a custom icon, configurable UI, and support for inputs and outputs.

In this guide, you’ll learn how to build your own custom workflow activity in Adobe Campaign Classic – step by step. We’ll cover everything from setting up the XML definition and writing your own JS logic, to adding a custom icon and testing/debugging the activity.

Unfortunately, there aren’t many resources available online on how to create custom activities. In fact, the only example widely shared is a PowerPoint presentation on the Adobe Community forums. Surprisingly, it connects the dots, showing how all the pieces come together in a real use case. This article builds on that foundation and takes it further with a hands-on, step-by-step guide.

To create a custom activity, we need to extend the xtk:workflow schema, modify the xtk:workflow form, and implement a JavaScript library to host the custom activity logic.

Extension of xtk:workflow schema

<srcSchema label="workflows">
  <element img="nms:activities/delivery.png" label="Custom Activity" name="customActivity" template="xtk:workflow:activity">
    <attribute default="nms:activities/delivery.png" name="img"/>
    <attribute default="cus:customActivityLibrary.js" name="library"/>

    <!-- attributes used by your activity -->
    <attribute label="Label" name="label" type="string"/>
    ..
    <!-- define transitions -->
    <element name="transitions">
      <element name="done" template="xtk:workflow:transition">
        <attribute name="label" translatedDefault="'Ok'"/>
      </element>
      <element name="error" template="xtk:workflow:transition">
        <attribute name="label" translatedDefault="'Error'"/>
      </element>
    </element>
  </element>
  
   <element desc="Workflows definitions" img="xtk:workflow.png" label="Workflows"
           labelSingular="Workflow" name="workflow">

	<!-- register activity under activities -->
    <element name="activities">
      <element name="customActivity" ref="customActivity" unbound="true"/>
    </element>
  </element>
</srcSchema>

Changing the xtk:workflow form

<!-- add activity in the coresponding activity section -->
<container applicableIf="$(entityPath)=='/operation'" codepage="1252" img="nms:miniatures/mini-delivery.png"
                 label="Deliveries" name="delivery">
  <input img="cus:customActivity-mini.png" label="customActivity" xpath="customActivity"/>
  
 </container
 <!-- add activity's form -->
  <form name="customActivity" type="notebook">
    <container img="cus:customActivity-mini.png">
      <input required="true" xpath="@label"/>
      ..
    </container>
  </form>
  ..
</container>

Implementing library cus:customActivityLibrary.js

//entry point for activation
function customActivity_call(){
  //do something for the first time
  return 0
}

//entry point for reactivation
function customActivity_recall() 
{

  //do something for consecutive times
  try {

    task.postEvent(task.doneTransition()) //we decide that a single call by the scheduler is enough, we activate the normal output transition
    task.setCompleted()
    
  }
  catch(e)
  {
    logError(JSON.stringify(e))
    task.postEvent(task.errorTransition()) //enable error transition
    task.setCompleted()
  }
  return 0
}

In the next section, I’ll dive deep into building custom activities, with a full step-by-step explanation on how to create one.

The simplest way to enhance Adobe Campaign Classic’s marketing capabilities is by integrating a Discord webhook, which allows you to send mes

đź”’ This content is for Premium Subsribers only.

Please log in to preview content. Log in or Register

You must log in and have a Premium Subscriber account to preview the content.

When upgrading, please use the same email address as your WordPress account so we can correctly link your Premium membership.

Please allow us a little time to process and upgrade your account after the purchase. If you need faster access or encounter any issues, feel free to contact us at info@martechnotes.com or through any other available channel.

To join the Discord community, please also provide your Discord username after subscribing, or reach out to us directly for access.

You can subscribe even before creating a WordPress account — your subscription will be linked to the email address used during checkout.

Premium Subscriber

19,99 € / Year

  • Free e-book with all revisions - 101 Adobe Campaign Classic (SFMC 101 in progress)
  • All Premium Subscriber Benefits - Exclusive blog content, weekly insights, and Discord community access
  • Lock in Your Price for a Full Year - Avoid future price increases
  • Limited Seats at This Price - Lock in early before it goes up

Oh hi there đź‘‹
I have a FREE e-book for you.

Sign up now to get an in-depth analysis of Adobe and Salesforce Marketing Clouds!

We don’t spam! Read our privacy policy for more info.

Share With Others

Leave a Comment

Your email address will not be published. Required fields are marked *

MarTech consultant

Marcel Szimonisz

Marcel Szimonisz

I specialize in solving problems, automating processes, and driving innovation through major marketing automation platforms—particularly Salesforce Marketing Cloud and Adobe Campaign.

Get exclusive technical tips—only available on my blog.

We don’t spam! Read our privacy policy for more info.

Buy me a coffee
Related posts