# Solutions By Text (SBT) Integration with Salesforce Marketing Cloud
## Technical Documentation

---

**Document Version:** 1.0
**Last Updated:** December 2024
**Prepared By:** Development Team
**Client:** Solutions By Text (SBT)

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [System Architecture Overview](#2-system-architecture-overview)
3. [Component Details](#3-component-details)
4. [Custom Activities](#4-custom-activities)
5. [API Endpoints and Routes](#5-api-endpoints-and-routes)
6. [Data Flow and Integration](#6-data-flow-and-integration)
7. [Configuration Files](#7-configuration-files)
8. [Frontend Components](#8-frontend-components)
9. [Postmonger Integration](#9-postmonger-integration)
10. [Security Considerations](#10-security-considerations)
11. [Error Handling](#11-error-handling)
12. [Deployment and Hosting](#12-deployment-and-hosting)
13. [Appendix](#13-appendix)

---

## 1. Executive Summary

### 1.1 Project Overview

Solutions By Text (SBT) is an SMS service provider that required a custom application for use within Salesforce Marketing Cloud (SFMC). The objective was to enable SBT's customers to seamlessly send large-scale marketing campaign SMS messages from SFMC to their end customers using SBT's API infrastructure.

### 1.2 Solution Summary

The integration was implemented using a **Custom Middleware Server** architecture that acts as a secure and scalable bridge between Salesforce Marketing Cloud and the SBT REST API. This middleware handles:

- Authentication and authorization
- Message formatting and personalization
- Template management
- URL shortening (SmartURL)
- API communication
- Reliable SMS delivery for bulk marketing campaigns

### 1.3 Key Features

| Feature | Description |
|---------|-------------|
| Plain Text SMS | Compose and send custom SMS messages with dynamic personalization |
| Template SMS | Use pre-defined templates with variable substitution |
| User-Defined Messages | Send messages where content is provided from journey data |
| MMS Support | Attach media URLs for multimedia messaging |
| SmartURL | Create trackable shortened URLs for SMS messages |
| Dynamic Personalization | Insert contact and event data fields into messages |
| Journey Builder Integration | Full integration with SFMC Journey Builder workflows |

---

## 2. System Architecture Overview

### 2.1 Three-Tier Architecture

The solution consists of three main components working together:

```
+------------------------------------------+
|     SALESFORCE MARKETING CLOUD (SFMC)    |
|  +------------------------------------+  |
|  |         Journey Builder            |  |
|  |  +------------------------------+  |  |
|  |  |    Custom Activity iFrame    |  |  |
|  |  |    (Frontend Application)    |  |  |
|  |  +------------------------------+  |  |
|  +------------------------------------+  |
+---------------------|--------------------+
                      | PostMessage API
                      | (Postmonger Library)
                      v
+------------------------------------------+
|     CUSTOM MIDDLEWARE SERVER             |
|     https://sbt.micronetbd.org           |
|  +------------------------------------+  |
|  |  - Authentication Handler          |  |
|  |  - Message Processing Engine       |  |
|  |  - Template Management             |  |
|  |  - URL Shortening Service          |  |
|  |  - Queue Management                |  |
|  |  - API Gateway                     |  |
|  +------------------------------------+  |
+---------------------|--------------------+
                      | REST API
                      | (HTTPS)
                      v
+------------------------------------------+
|          SBT SMS PLATFORM                |
|  +------------------------------------+  |
|  |  - SMS Gateway                     |  |
|  |  - Message Delivery                |  |
|  |  - Carrier Integration             |  |
|  |  - Delivery Reports                |  |
|  +------------------------------------+  |
+------------------------------------------+
```

### 2.2 Component Responsibilities

| Component | Responsibility |
|-----------|---------------|
| **SFMC Journey Builder** | Campaign orchestration, contact management, journey triggers |
| **Custom Activity (Frontend)** | User interface for message configuration, field mapping |
| **Middleware Server** | Authentication, message processing, API routing, URL shortening |
| **SBT Platform** | SMS delivery, carrier management, delivery reporting |

### 2.3 Technology Stack

**Frontend (Custom Activities):**
- HTML5 / CSS3
- JavaScript (ES6+)
- jQuery 3.7.1
- RequireJS 2.3.7 (AMD module loader)
- Axios (HTTP client for template activity)
- Bootstrap 5.3.3 (UI framework)
- Postmonger 0.0.14 (SFMC communication library)

**Backend (Middleware Server):**
- Host: `https://sbt.micronetbd.org`
- REST API architecture
- HTTPS/TLS encryption

---

## 3. Component Details

### 3.1 Project Directory Structure

```
sbt-mc-activity-new/
|
+-- plain-text-activity/
|   +-- mc/
|       +-- v8/                          # Latest Plain Text Activity (Version 8)
|           +-- config.js                # AMD configuration module
|           +-- config.json              # SFMC activity configuration
|           +-- customActivity.js        # Main activity logic
|           +-- index.html               # Activity UI
|           +-- postmonger.js            # SFMC communication library
|           +-- images/
|               +-- sms.png              # Activity icon
|
+-- template-activity/
|   +-- mc/
|       +-- v11/                         # Latest Template Activity (Version 11)
|           +-- config.js
|           +-- config.json
|           +-- customActivity.js
|           +-- index.html
|           +-- postmonger.js
|
+-- user-defined-message/
|   +-- v1/                              # User-Defined Message Activity (Version 1)
|       +-- config.js
|       +-- config.json
|       +-- customActivity.js
|       +-- index.html
|       +-- postmonger.js
|
+-- v3/                                  # Legacy Plain Text Activity (Version 3)
|   +-- config.js
|   +-- config.json
|   +-- customActivity.js
|   +-- index.html
|   +-- index1.html
|   +-- index3.html
|   +-- postmonger.js
|   +-- images/
|       +-- sms.png
|
+-- images/
|   +-- sms.png                          # Shared SMS icon
|
+-- .gitignore
```

### 3.2 Version History

| Activity Type | Current Version | Description |
|--------------|-----------------|-------------|
| Plain Text Activity | V8 | Custom SMS message composition |
| Template Activity | V11 | Template-based messaging |
| User-Defined Message | V1 | Event-driven message pass-through |

---

## 4. Custom Activities

### 4.1 Plain Text Activity (v8)

**Purpose:** Enables marketers to compose custom SMS messages with dynamic personalization fields.

**Key Features:**
- Free-form text message composition
- Dynamic field insertion (Contact and Event data)
- Message preview with sample data
- SmartURL creation and insertion
- MMS media URL support

**Location:** `/plain-text-activity/mc/v8/`

**User Interface Elements:**

| Element ID | Type | Purpose |
|-----------|------|---------|
| `#mess` | Textarea | Message composition area |
| `#fieldDropdown` | Select | Dynamic field selection |
| `#insertFieldBtn` | Button | Insert selected field at cursor |
| `#previewBtn` | Button | Generate message preview |
| `#previewContent` | Div | Display preview with sample data |
| `#media` | Input | MMS media URL |
| `#longUrl` | Input | URL to shorten |
| `#shortenBtn` | Button | Trigger URL shortening |
| `#shortUrl` | Input | Display shortened URL |
| `#insertShortUrlBtn` | Button | Insert short URL into message |
| `#setmess` | Button | Confirm and save message |

**Available Dynamic Fields:**

*Contact Fields:*
| Field Name | Token |
|------------|-------|
| Contact Key | `{{Contact.Key}}` |
| Email | `{{Contact.Attribute.Email}}` |
| First Name | `{{Contact.Attribute.FirstName}}` |
| Last Name | `{{Contact.Attribute.LastName}}` |
| Phone | `{{Contact.Attribute.Phone}}` |
| Mobile Number | `{{Contact.Attribute.MobileNumber}}` |

*Event Data Fields (dynamically generated based on entry event):*
| Field Pattern | Example |
|--------------|---------|
| `{{Event.[eventKey].[FieldName]}}` | `{{Event.APIEvent-123.Email}}` |

---

### 4.2 Template Activity (v11)

**Purpose:** Enables marketers to send SMS messages using pre-defined templates with variable mapping.

**Key Features:**
- Template selection from SBT platform
- Automatic variable extraction from templates
- Dynamic field mapping for each variable
- Static value support for variables
- Template preview
- SmartURL creation
- MMS media URL support

**Location:** `/template-activity/mc/v11/`

**User Interface Elements:**

| Element ID | Type | Purpose |
|-----------|------|---------|
| `#templateSelect` | Select | Template selection dropdown |
| `#templatePreview` | Div | Display template message text |
| `#variablesBlock` | Div | Container for variable inputs |
| `#variablesContainer` | Div | Dynamic variable mapping inputs |
| `#media` | Input | MMS media URL |
| `#tmplLongUrl` | Input | URL to shorten |
| `#tmplShortenBtn` | Button | Trigger URL shortening |
| `#tmplShortUrl` | Input | Display shortened URL |
| `#validationError` | Div | Validation error messages |
| `#templatesError` | Div | Template loading error messages |

**Variable Mapping Structure:**

Templates contain placeholders in the format `{variableName}`. Each variable can be mapped to:
1. **Dynamic Field** - A contact or event data token
2. **Static Value** - A fixed text value

Example template:
```
Hello {FirstName}, your account balance is {Balance}. Visit {Link} for details.
```

Variables extracted: `FirstName`, `Balance`, `Link`

---

### 4.3 User-Defined Message Activity (v1)

**Purpose:** Enables sending SMS messages where the message content is provided directly from the journey entry event data.

**Key Features:**
- Minimal configuration required
- Message content sourced from event data
- Pass-through architecture
- Ideal for triggered/transactional messages

**Location:** `/user-defined-message/v1/`

**Data Token Structure:**

| Token | Description |
|-------|-------------|
| `{{Contact.key}}` | Subscriber/Contact unique key |
| `{{Event.[key].Phone}}` | Phone number from event data |
| `{{Event.[key].Email}}` | Email from event data |
| `{{Event.[key].Id}}` | Record ID from event data |
| `{{Event.[key].Message}}` | Message content from event data |

---

## 5. API Endpoints and Routes

### 5.1 Base URL

```
https://sbt.micronetbd.org
```

### 5.2 Journey Execution Endpoints

| Endpoint | Method | Activity Type | Description |
|----------|--------|---------------|-------------|
| `/journey/execute` | POST | Plain Text, User-Defined | Execute plain text SMS message |
| `/journey/execute/template` | POST | Template | Execute template-based SMS message |

### 5.3 Configuration Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/journey/save` | POST | Save activity configuration |
| `/journey/publish` | POST | Publish journey activity |
| `/journey/validate` | POST | Validate activity configuration |
| `/journey/stop` | POST | Stop/cancel journey activity |

### 5.4 Utility Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/short-url` | POST | Create SmartURL (shortened URL) |
| `/api/get-all-templates` | GET | Retrieve list of available SMS templates |

---

### 5.5 Request/Response Schemas

#### 5.5.1 Plain Text Activity - Execute

**Endpoint:** `POST /journey/execute`

**Request Payload (inArguments):**
```json
[
  {
    "message": "Hello {{Contact.Attribute.FirstName}}, your order #{{Event.APIEvent.OrderId}} is ready!",
    "media": "https://example.com/image.jpg"
  },
  {
    "subscriberKey": "{{Contact.Key}}",
    "Phone": "{{Event.APIEvent.Phone}}",
    "Email": "{{Event.APIEvent.Email}}",
    "Id": "{{Event.APIEvent.Id}}",
    "tssd": "{{Event.APIEvent.tssd}}"
  }
]
```

**Response (outArguments):**
```json
[
  {
    "success": true
  }
]
```

---

#### 5.5.2 Template Activity - Execute

**Endpoint:** `POST /journey/execute/template`

**Request Payload (inArguments):**
```json
[
  {
    "messageStructure": {
      "isTemplate": true,
      "templateId": "12345",
      "Variables": [
        {
          "name": "FirstName",
          "value": "{{Contact.Attribute.FirstName}}"
        },
        {
          "name": "Balance",
          "value": "$250.00"
        },
        {
          "name": "Link",
          "value": "https://sbt.ly/abc123"
        }
      ],
      "media": ""
    },
    "media": ""
  },
  {
    "subscriberKey": "{{Contact.Key}}",
    "Phone": "{{Event.APIEvent.Phone}}",
    "Email": "{{Event.APIEvent.Email}}",
    "Id": "{{Event.APIEvent.Id}}",
    "tssd": "{{Event.APIEvent.tssd}}"
  }
]
```

**Response (outArguments):**
```json
[
  {
    "success": true
  }
]
```

---

#### 5.5.3 Short URL Creation

**Endpoint:** `POST /api/short-url`

**Request:**
```json
{
  "longUrl": "https://example.com/very/long/path/to/page.html?param=value"
}
```

**Response:**
```json
{
  "ok": true,
  "shortUrl": "https://sbt.ly/abc123"
}
```

---

#### 5.5.4 Get All Templates

**Endpoint:** `GET /api/get-all-templates`

**Response:**
```json
{
  "data": [
    {
      "id": 12345,
      "name": "Welcome Message",
      "message": "Hello {FirstName}, welcome to {CompanyName}!",
      "status": "active"
    },
    {
      "id": 12346,
      "name": "Payment Reminder",
      "message": "Hi {FirstName}, your payment of {Amount} is due on {DueDate}.",
      "status": "active"
    }
  ]
}
```

---

## 6. Data Flow and Integration

### 6.1 Complete Data Flow Diagram

```
+-------------------------------------------------------------------------+
|                    SALESFORCE MARKETING CLOUD                            |
+-------------------------------------------------------------------------+
|                                                                         |
|  1. JOURNEY CREATION & CONFIGURATION                                    |
|  +-------------------------------------------------------------------+  |
|  |  Journey Builder                                                   |  |
|  |    |                                                               |  |
|  |    +-- Entry Source (Data Extension, API Event, etc.)             |  |
|  |    |      |                                                        |  |
|  |    |      +-- Contact Data: Email, Phone, FirstName, LastName     |  |
|  |    |      +-- Event Data: Custom fields from trigger              |  |
|  |    |                                                               |  |
|  |    +-- Custom Activity (SBT SMS)                                   |  |
|  |           |                                                        |  |
|  |           +-- Opens config modal (iFrame)                          |  |
|  |           +-- Loads customActivity.js                              |  |
|  +-------------------------------------------------------------------+  |
|                          |                                               |
|                          | Postmonger.Session()                          |
|                          v                                               |
|  2. ACTIVITY CONFIGURATION (iFrame)                                     |
|  +-------------------------------------------------------------------+  |
|  |  Custom Activity UI                                                |  |
|  |    |                                                               |  |
|  |    +-- connection.trigger("ready")                                |  |
|  |    +-- connection.trigger("requestTokens")                        |  |
|  |    +-- connection.trigger("requestSchema")                        |  |
|  |    +-- connection.trigger("requestTriggerEventDefinition")        |  |
|  |    |                                                               |  |
|  |    +-- User configures message                                     |  |
|  |    |      +-- Composes text OR selects template                   |  |
|  |    |      +-- Maps dynamic fields                                  |  |
|  |    |      +-- Optionally creates SmartURL                          |  |
|  |    |      +-- Optionally adds media URL                            |  |
|  |    |                                                               |  |
|  |    +-- connection.trigger("updateActivity", payload)              |  |
|  +-------------------------------------------------------------------+  |
|                          |                                               |
+--------------------------|----------------------------------------------+
                           |
                           | Journey Published & Activated
                           |
+--------------------------|----------------------------------------------+
|                          v                                               |
|  3. JOURNEY EXECUTION (Runtime)                                         |
|  +-------------------------------------------------------------------+  |
|  |  Contact enters journey via trigger                                |  |
|  |    |                                                               |  |
|  |    +-- SFMC substitutes tokens with actual values                 |  |
|  |    |      {{Contact.Key}} --> "CONTACT-12345"                     |  |
|  |    |      {{Event.key.Phone}} --> "+15551234567"                  |  |
|  |    |      {{Contact.Attribute.FirstName}} --> "John"              |  |
|  |    |                                                               |  |
|  |    +-- SFMC sends POST request to middleware                       |  |
|  +-------------------------------------------------------------------+  |
|                          |                                               |
+--------------------------|----------------------------------------------+
                           |
                           | HTTPS POST to /journey/execute
                           |
+--------------------------|----------------------------------------------+
|                          v                                               |
|                 MIDDLEWARE SERVER                                        |
|            https://sbt.micronetbd.org                                    |
+-------------------------------------------------------------------------+
|                                                                         |
|  4. MESSAGE PROCESSING                                                  |
|  +-------------------------------------------------------------------+  |
|  |  Receive Request                                                   |  |
|  |    |                                                               |  |
|  |    +-- Validate authentication (SFMC JWT/tokens)                  |  |
|  |    +-- Parse inArguments                                           |  |
|  |    +-- Extract message content and recipient data                  |  |
|  |    |                                                               |  |
|  |  Process Message                                                    |  |
|  |    |                                                               |  |
|  |    +-- For Plain Text: Use message as-is                          |  |
|  |    +-- For Template: Fetch template, substitute variables         |  |
|  |    +-- Validate phone number format                                |  |
|  |    +-- Apply any business rules                                    |  |
|  |    |                                                               |  |
|  |  Queue for Delivery                                                 |  |
|  |    |                                                               |  |
|  |    +-- Add to message queue                                        |  |
|  |    +-- Return success response to SFMC                             |  |
|  +-------------------------------------------------------------------+  |
|                          |                                               |
+--------------------------|----------------------------------------------+
                           |
                           | SBT API Call
                           |
+--------------------------|----------------------------------------------+
|                          v                                               |
|                    SBT SMS PLATFORM                                      |
+-------------------------------------------------------------------------+
|                                                                         |
|  5. SMS DELIVERY                                                        |
|  +-------------------------------------------------------------------+  |
|  |  Message Gateway                                                   |  |
|  |    |                                                               |  |
|  |    +-- Route to appropriate carrier                                |  |
|  |    +-- Deliver SMS to recipient                                    |  |
|  |    +-- Track delivery status                                       |  |
|  |    +-- Generate delivery reports                                   |  |
|  +-------------------------------------------------------------------+  |
|                                                                         |
+-------------------------------------------------------------------------+
```

---

### 6.2 Postmonger Event Flow

```
+------------------+                    +------------------+
|   Journey        |                    |   Custom         |
|   Builder        |                    |   Activity       |
+--------+---------+                    +--------+---------+
         |                                       |
         |  -------- Activity Opened --------->  |
         |                                       |
         |  <-------- "ready" -----------------  |
         |                                       |
         |  -------- "initActivity" ---------->  |
         |         (with saved payload)          |
         |                                       |
         |  <------ "requestTokens" -----------  |
         |  <------ "requestEndpoints" --------  |
         |  <------ "requestSchema" -----------  |
         |  <------ "requestTriggerEventDef" --  |
         |                                       |
         |  -------- "requestedSchema" ------->  |
         |  -------- "requestedTokens" ------->  |
         |  -------- "requestedEventDef" ----->  |
         |                                       |
         |       [User configures activity]      |
         |                                       |
         |  <------ "updateButton" ------------  |
         |         (enable/disable Next)         |
         |                                       |
         |  -------- "clickedNext" ----------->  |
         |                                       |
         |  <------ "updateActivity" ----------  |
         |         (with final payload)          |
         |                                       |
         |  -------- Activity Saved ---------->  |
         |                                       |
+--------+---------+                    +--------+---------+
```

---

### 6.3 Token Substitution Process

**Stage 1: Configuration Time**
- User selects dynamic fields in the UI
- Fields are stored as tokens: `{{Contact.Attribute.FirstName}}`

**Stage 2: Runtime Substitution**
- When a contact enters the journey, SFMC substitutes tokens:

| Token | Substituted Value |
|-------|-------------------|
| `{{Contact.Key}}` | `CONTACT-ABC123` |
| `{{Contact.Attribute.FirstName}}` | `John` |
| `{{Contact.Attribute.Email}}` | `john@example.com` |
| `{{Event.APIEvent-456.Phone}}` | `+15551234567` |
| `{{Event.APIEvent-456.OrderId}}` | `ORD-789` |

**Stage 3: Message Delivery**
- Fully substituted message is sent to middleware
- Middleware processes and delivers via SBT platform

---

## 7. Configuration Files

### 7.1 config.json Structure

The `config.json` file defines how the custom activity integrates with SFMC Journey Builder.

**Plain Text Activity Configuration:**

```json
{
  "workflowApiVersion": "1.1",
  "metaData": {
    "icon": "images/sms.png",
    "category": "message"
  },
  "type": "REST",
  "lang": {
    "en-US": {
      "name": "SBT Plain Message V3",
      "description": "Send SBT Message by SBT"
    }
  },
  "arguments": {
    "execute": {
      "inArguments": [
        {
          "emailAddress": "{{InteractionDefaults.Email}}"
        },
        {
          "phoneNumber": "{{InteractionDefaults.Phone}}"
        }
      ],
      "outArguments": [
        {
          "success": ""
        }
      ],
      "url": "https://sbt.micronetbd.org/journey/execute"
    }
  },
  "configurationArguments": {
    "save": {
      "url": "https://sbt.micronetbd.org/journey/save"
    },
    "publish": {
      "url": "https://sbt.micronetbd.org/journey/publish"
    },
    "validate": {
      "url": "https://sbt.micronetbd.org/journey/validate"
    },
    "stop": {
      "url": "https://sbt.micronetbd.org/journey/stop"
    }
  },
  "userInterfaces": {
    "configModal": {
      "height": 450,
      "width": 800,
      "fullscreen": false
    }
  },
  "schema": {
    "arguments": {
      "execute": {
        "inArguments": [
          {
            "phoneNumber": {
              "dataType": "Phone",
              "isNullable": false,
              "direction": "in"
            }
          },
          {
            "emailAddress": {
              "dataType": "Email",
              "isNullable": false,
              "direction": "in"
            }
          }
        ],
        "outArguments": [
          {
            "success": {
              "dataType": "Boolean",
              "direction": "out",
              "access": "visible"
            }
          }
        ]
      }
    }
  }
}
```

### 7.2 Configuration Properties Explained

| Property | Description |
|----------|-------------|
| `workflowApiVersion` | SFMC workflow API version (1.1) |
| `metaData.icon` | Path to activity icon displayed in Journey Builder |
| `metaData.category` | Activity category ("message" for SMS) |
| `type` | Integration type ("REST" for HTTP-based) |
| `lang` | Localized name and description |
| `arguments.execute.url` | Endpoint called when journey executes |
| `arguments.execute.inArguments` | Data sent to middleware at execution |
| `arguments.execute.outArguments` | Data returned from middleware |
| `configurationArguments` | Lifecycle event endpoints (save, publish, validate, stop) |
| `userInterfaces.configModal` | iFrame dimensions for configuration UI |
| `schema` | Data type definitions for arguments |

---

## 8. Frontend Components

### 8.1 Postmonger Library

**Version:** 0.0.14

**Purpose:** Enables secure cross-origin communication between the custom activity iFrame and SFMC Journey Builder.

**Key Classes:**

| Class | Purpose |
|-------|---------|
| `Postmonger.Session` | Main communication session with Journey Builder |
| `Postmonger.Connection` | Low-level connection management |
| `Postmonger.Events` | Event handling system |

**Usage Pattern:**
```javascript
var connection = new Postmonger.Session();

// Signal ready to Journey Builder
connection.trigger("ready");

// Listen for initialization data
connection.on("initActivity", function(payload) {
  // Restore saved state
});

// Request data from Journey Builder
connection.trigger("requestSchema");
connection.trigger("requestTriggerEventDefinition");

// Listen for responses
connection.on("requestedSchema", function(schema) {
  // Process schema data
});

// Save activity configuration
connection.trigger("updateActivity", payload);
```

---

### 8.2 RequireJS Module Structure

**Base Configuration:**
```javascript
(function() {
  var config = { baseUrl: "" };
  var dependencies = ["customActivity"];
  require(config, dependencies);
})();
```

**Module Definition (customActivity.js):**
```javascript
define(["postmonger"], function(Postmonger) {
  "use strict";

  var connection = new Postmonger.Session();

  // Activity logic here

});
```

---

### 8.3 UI Styling

**SBT Brand Colors:**

| CSS Variable | Value | Usage |
|-------------|-------|-------|
| `--sbt-primary` | `#0F3D91` | Primary brand color |
| `--sbt-primary-600` | `#0b2e6d` | Darker primary variant |
| `--sbt-accent` | `#28C76F` | Accent/success color |
| `--sbt-bg` | `#f5f7fb` | Background color |
| `--sbt-card` | `#ffffff` | Card background |
| `--sbt-border` | `#e7ebf3` | Border color |
| `--sbt-muted` | `#6b7280` | Muted text |
| `--sbt-text` | `#1f2937` | Primary text |

---

## 9. Postmonger Integration

### 9.1 Event Listeners

| Event | Description | Handler Function |
|-------|-------------|------------------|
| `initActivity` | Receive saved activity configuration | `initialize(payload)` |
| `clickedNext` | User clicked Next/Done button | `onClickedNext()` |
| `clickedBack` | User clicked Back button | `onClickedBack()` |
| `gotoStep` | Navigate to specific step | `onGotoStep(step)` |
| `requestedTriggerEventDefinition` | Receive event definition data | `getEventTriggerDefinition(def)` |
| `requestedSchema` | Receive contact/entry schema | `onRequestedSchema(schema)` |
| `requestedInteraction` | Receive journey interaction data | `onRequestedInteraction(interaction)` |

### 9.2 Event Triggers

| Trigger | Description | Parameters |
|---------|-------------|------------|
| `ready` | Signal activity is ready | None |
| `requestTokens` | Request SFMC authentication tokens | None |
| `requestEndpoints` | Request SFMC endpoints | None |
| `requestTriggerEventDefinition` | Request entry event data structure | None |
| `requestSchema` | Request contact/event schema | None |
| `requestInteraction` | Request journey interaction details | None |
| `updateButton` | Control Next/Back button state | `{button, text, visible, enabled}` |
| `updateActivity` | Save activity configuration | `payload` object |
| `prevStep` | Navigate to previous step | None |

---

## 10. Security Considerations

### 10.1 Authentication & Authorization

| Layer | Mechanism |
|-------|-----------|
| SFMC to Activity | Postmonger session (browser PostMessage API) |
| SFMC to Middleware | SFMC JWT tokens (handled by platform) |
| Middleware to SBT | API authentication (backend) |

### 10.2 Security Features

- **HTTPS Only:** All endpoints use TLS encryption
- **No Credentials in Frontend:** API keys and secrets stored only on backend
- **CORS Configuration:** Backend must allow requests from SFMC domains
- **Token-Based Auth:** SFMC handles OAuth/JWT token management
- **Input Validation:** Phone numbers and URLs validated before processing
- **XSS Prevention:** User input escaped/sanitized in preview functions

### 10.3 Data Protection

- Contact data tokens substituted at runtime by SFMC
- Personal data not stored in frontend localStorage or cookies
- Message content encrypted in transit
- No sensitive data logged in browser console (production)

---

## 11. Error Handling

### 11.1 Frontend Error Handling

**Short URL Creation Errors:**
```javascript
try {
  const resp = await $.ajax({
    url: "https://sbt.micronetbd.org/api/short-url",
    method: "POST",
    contentType: "application/json",
    data: JSON.stringify({ longUrl })
  });

  if (!resp || !resp.ok || !resp.shortUrl) {
    $("#shortUrlError").text("Failed to shorten URL.");
    return;
  }
} catch (e) {
  console.error("Short URL error", e);
  $("#shortUrlError").text("Error contacting short URL service.");
}
```

**Template Loading Errors:**
```javascript
axios.get("https://sbt.micronetbd.org/api/get-all-templates")
  .then(function(res) {
    // Success handling
  })
  .catch(function() {
    elTmplErr.textContent = "Failed to load templates (possibly a CORS issue).";
  });
```

### 11.2 Validation Errors

| Validation | Error Message | Location |
|------------|---------------|----------|
| No template selected | "Please select a template." | `#validationError` |
| Invalid media URL | "Media URL must start with http:// or https://" | `#validationError` |
| Empty short URL input | "Please enter a URL to shorten." | `#shortUrlError` |
| Template load failure | "Failed to load templates (possibly a CORS issue)." | `#templatesError` |

---

## 12. Deployment and Hosting

### 12.1 Hosting Requirements

**Frontend (Custom Activities):**
- Static file hosting (HTML, CSS, JS)
- HTTPS certificate required
- CORS headers for SFMC domains
- CDN recommended for performance

**Current Hosting:**
- Activity Assets: `https://activity.micronetbd.org/`
- Backend API: `https://sbt.micronetbd.org/`

### 12.2 External Dependencies (CDN)

| Resource | URL | Version |
|----------|-----|---------|
| jQuery | `https://code.jquery.com/jquery-3.7.1.min.js` | 3.7.1 |
| RequireJS | `https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.7/require.min.js` | 2.3.7 |
| Axios | `https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js` | Latest |
| Bootstrap CSS | `https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css` | 5.3.3 |

### 12.3 SFMC Package Installation

1. Create Installed Package in SFMC Setup
2. Add Custom Activity component
3. Configure endpoint URLs
4. Set activity category and icon
5. Deploy to appropriate Business Units

---

## 13. Appendix

### 13.1 Glossary

| Term | Definition |
|------|------------|
| **SFMC** | Salesforce Marketing Cloud |
| **SBT** | Solutions By Text (SMS service provider) |
| **Journey Builder** | SFMC campaign orchestration tool |
| **Custom Activity** | Third-party integration in Journey Builder |
| **Postmonger** | SFMC's JavaScript library for custom activity communication |
| **SmartURL** | Trackable shortened URL created by SBT platform |
| **MMS** | Multimedia Messaging Service (SMS with media) |
| **inArguments** | Data sent from SFMC to middleware at execution |
| **outArguments** | Data returned from middleware to SFMC |
| **Data Extension** | SFMC database table for storing contact data |
| **Event Definition** | Schema defining entry event data structure |

### 13.2 Complete Endpoint Reference

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `https://sbt.micronetbd.org/journey/execute` | POST | Execute plain text SMS |
| `https://sbt.micronetbd.org/journey/execute/template` | POST | Execute template SMS |
| `https://sbt.micronetbd.org/journey/save` | POST | Save activity config |
| `https://sbt.micronetbd.org/journey/publish` | POST | Publish journey |
| `https://sbt.micronetbd.org/journey/validate` | POST | Validate config |
| `https://sbt.micronetbd.org/journey/stop` | POST | Stop journey |
| `https://sbt.micronetbd.org/api/short-url` | POST | Create SmartURL |
| `https://sbt.micronetbd.org/api/get-all-templates` | GET | List templates |

### 13.3 Sample Payload Structures

**Complete Plain Text Activity Payload:**
```json
{
  "name": "Hello {{Contact.Attribute.FirstName}}, thank you for your order!",
  "arguments": {
    "execute": {
      "inArguments": [
        {
          "message": "Hello {{Contact.Attribute.FirstName}}, thank you for your order #{{Event.APIEvent.OrderId}}!",
          "media": "https://example.com/thank-you.jpg"
        },
        {
          "subscriberKey": "{{Contact.Key}}",
          "Phone": "{{Event.APIEvent.Phone}}",
          "Email": "{{Event.APIEvent.Email}}",
          "Id": "{{Event.APIEvent.Id}}",
          "tssd": "{{Event.APIEvent.tssd}}"
        }
      ],
      "outArguments": [
        {
          "success": ""
        }
      ]
    }
  },
  "metaData": {
    "isConfigured": true
  }
}
```

**Complete Template Activity Payload:**
```json
{
  "name": "Template: Welcome Message",
  "arguments": {
    "execute": {
      "inArguments": [
        {
          "messageStructure": {
            "isTemplate": true,
            "templateId": "12345",
            "Variables": [
              {
                "name": "FirstName",
                "value": "{{Contact.Attribute.FirstName}}"
              },
              {
                "name": "CompanyName",
                "value": "Solutions By Text"
              }
            ],
            "media": ""
          },
          "media": ""
        },
        {
          "subscriberKey": "{{Contact.Key}}",
          "Phone": "{{Event.APIEvent.Phone}}",
          "Email": "{{Event.APIEvent.Email}}",
          "Id": "{{Event.APIEvent.Id}}",
          "tssd": "{{Event.APIEvent.tssd}}"
        }
      ],
      "outArguments": [
        {
          "success": ""
        }
      ]
    }
  },
  "metaData": {
    "isConfigured": true
  }
}
```

---

## Document Control

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0 | December 2024 | Development Team | Initial documentation |

---

**End of Document**
