Guide · Creation Walkthrough

Creating an SFMC Journey Builder Custom Activity (Complete Guide)

From an empty Marketing Cloud account to a deployed custom activity that registers inside Journey Builder — five clean steps, with the SFMC-side configuration screens, the backend scaffold, and the deployment checklist.

SFMC · SetupRead time · 9 minUpdated · May 2026By Lalit Chaudhari
01 — Introduction

What you'll have at the end.

A custom activity registered in Marketing Cloud, published into Journey Builder, with a Node.js service hosting the four lifecycle endpoints. After this guide your activity will show up in the canvas palette and respond to test contacts you push through it.

For the system-level architecture, see the full SFMC Custom Activity Tutorial. This guide is the creation procedure.

02 — Prerequisites

What you need before starting.

  • A Marketing Cloud account with Administrator access
  • Journey Builder enabled in your Business Unit
  • A public HTTPS endpoint (or a tunnel like ngrok for dev)
  • Node.js 18+ and a package manager (npm / pnpm / bun)
  • Basic familiarity with Express and JSON
  • An idea of what your activity should do at runtime
Step 01

Create the Installed Package.

The Installed Package is the SFMC-side container for your activity. It owns the JWT signing secret you'll use to verify runtime calls.

  1. 01Open Setup → Platform Tools → Apps → Installed Packages
  2. 02Click New, give it a clear name (e.g. "Slack Notifier")
  3. 03Save — this generates the JWT signing secret
  4. 04Copy the JWT secret into your backend's environment variables as SFMC_JWT_SECRET
Setup · Installed Packagesscreenshot
SFMC Setup → Installed Packages — package details with Summary (Name, Description, Type Custom, Status In Development, Source Account, Package Id, JWT Signing Secret) and Components section listing API Integration with Client Id, Client Secret, Authentication Base URI, REST and SOAP base URIs, and Scope permissions.
The Installed Package screen — copy the JWT Signing Secret into your backend's SFMC_JWT_SECRET environment variable.
Step 02

Add the Journey Builder Activity component.

Inside your Installed Package, click Add Component → Journey Builder Activity. Point the endpoint base URL at where your Node.js service will be hosted.

Heads up · Public HTTPS only
Journey Builder will not call non-HTTPS endpoints. For local development, use a tool like ngrok or cloudflared to expose your local Express server with a real cert.
Step 03

Configure the lifecycle endpoints.

The activity's config.json is the contract between Marketing Cloud and your service. It declares the URLs, the runtime arguments, and the JWT signing requirement.

config.jsonjson
{
  "workflowApiVersion": "1.1",
  "metaData": { "icon": "images/slack.png", "category": "messaging" },
  "type": "REST",
  "arguments": { "execute": {
    "url": "https://your-host.com/execute",
    "verb": "POST",
    "useJwt": true
  } },
  "configurationArguments": {
    "save":     { "url": "https://your-host.com/save" },
    "validate": { "url": "https://your-host.com/validate" },
    "publish":  { "url": "https://your-host.com/publish" }
  }
}
Step 04

Build the Node.js backend.

A minimal Express scaffold with all four endpoints wired. Drop this file in, install express and jsonwebtoken, and you're ready to register the activity.

server.jsnode
import express from "express";
import jwt from "jsonwebtoken";

const app = express();
app.use(express.json());
app.use(express.text({ type: "application/jwt" }));

// Configuration endpoints — open during canvas editing
app.post("/save",     (req, res) => res.json({ status: "saved" }));
app.post("/validate", (req, res) => res.json({ status: "ok" }));
app.post("/publish",  (req, res) => res.json({ status: "published" }));

// Runtime endpoint — JWT-signed
app.post("/execute", (req, res) => {
  const body = jwt.verify(req.body, process.env.SFMC_JWT_SECRET);
  // body.inArguments[0] holds your config + contact data
  doSideEffect(body.inArguments[0]);
  res.json({ status: "executed" });
});

app.listen(3000);
Tip · Logging
Log every /execute call with the activityInstanceId, the contact key, and a hash of the inArguments. Journey Builder retries are loud, but you'll wish you had structured logs the first time something silently fails.
Step 05

Deploy and test the journey end-to-end.

Deploy the Node.js service. Then go back into Journey Builder, build a small test journey with one entry source (a Data Extension with two test contacts) and your new activity, and run it.

  1. 01Deploy the backend to Vercel / Render / your platform of choice
  2. 02Confirm /save, /validate, /publish, /execute respond 200 to a curl test
  3. 03Refresh Journey Builder — your activity now appears in the palette
  4. 04Build a small journey with two test contacts and activate it
  5. 05Watch your service logs and confirm /execute fires per contact
Journey Builderscreenshot
Empty Journey Builder canvas after publishing the package — Activities palette shows Email, In-App Message, Inbox, Push Notification, Slack Message, SMS, WhatsApp under Messages, with the new Slack Message custom activity ready to drag onto the canvas.
After deploying and republishing the Installed Package, the new activity appears in the Journey Builder palette under Messages — ready to drag onto an empty canvas.
Next steps

Where to go from here.

FAQ

Quick answers.

Do I need a developer license to create an SFMC custom activity?
No — any Marketing Cloud edition that includes Journey Builder lets you register Installed Packages. You'll need a user with Administrator scope to create and edit packages.
Can I host the custom activity backend on the same domain as my customer.html UI?
Yes, and it's the recommended setup. Hosting the activity UI and the lifecycle endpoints on the same origin avoids cross-origin headaches inside the Journey Builder iframe.
How long does Journey Builder take to recognize a newly published activity?
Once you save the Journey Builder Activity component in your Installed Package, it appears in the canvas palette immediately. A hard refresh of the Journey Builder UI is sometimes needed.

Stuck on Installed Package setup?

I've shipped custom activities into production for marketing teams — happy to take a look at your Marketing Cloud setup or build it for you.

Get help