Product Guide How It Works Administration Support Guide Owner Guide Engine Core

Campaign Manager - Product Guide

Complete product overview - what Campaign Manager is, how campaigns are built, templates, AI features, microsites, and the Customer App

1. Overview

Campaign Manager (Velocity Engine) is a platform for building, managing, and executing marketing campaigns at scale. It combines a structured campaign pipeline - where each campaign is broken into phases, steps, and computation variables - with powerful AI/LLM content generation across multiple providers (OpenAI, Anthropic Claude, Google Gemini, Perplexity, AWS Bedrock).

Users design campaign workflows, provide inputs, and the system computes outputs using templates, scripts, and AI prompts, ultimately producing ready-to-publish assets that can be deployed to company microsites.

Two Applications, Two Audiences

ApplicationAudienceExperience
Admin ConsoleCampaign designers, admins, operatorsFull management: variable grid, storage, templates, security, AI model config, audit trails
Customer AppMarketing professionals, end usersGuided 5-step wizard: fill in forms, the system generates campaign content via AI

Architecture Overview

graph TB
    subgraph Users
        Admin["Admin Console
(full management)"] Customer["Customer App
(5-step wizard)"] end subgraph Backend["Campaign Manager Backend"] API["REST API
55+ controllers, 200+ endpoints"] Compute["Computation Engine
DAG executor, multi-threaded"] WS["WebSocket
real-time progress"] Script["Scripting Engine
JavaScript functions"] end subgraph AI["AI / LLM Providers"] OpenAI["OpenAI (GPT-4, DALL-E)"] Claude["Anthropic Claude"] Gemini["Google Gemini"] Perplexity["Perplexity"] Bedrock["AWS Bedrock"] end subgraph Infra["Infrastructure"] DB[(PostgreSQL)] S3["S3 File Storage"] CF["CloudFront CDN"] R53["Route53 DNS"] Agents["External AI Agents
(A2A proxy)"] end Admin -->|REST + WebSocket| API Customer -->|REST + WebSocket| API API --> Compute Compute --> AI Compute --> Script API --> WS API --> DB API --> S3 S3 --> CF CF --> R53 API -->|/a2a proxy| Agents

2. How a Campaign Is Built

A campaign in Campaign Manager is not a flat document - it is a structured computation pipeline. Understanding the hierarchy is key to understanding why the system works the way it does.

What Is a Campaign?

A campaign is a project container that holds everything needed to produce marketing deliverables: strategy inputs, AI-generated content, formatted documents, and publishable assets. The system structures this work into a hierarchy so that different pieces can be worked on independently, computed selectively, and exported or imported at any level.

Why Phases Exist

Think of phases as chapters in a book. Each phase groups related work into a logical stage of the campaign process. For example, a campaign might have three phases: "Research", "Content Creation", and "Review". Phases let you:

Why Steps Exist

Think of steps as pages in a chapter. Each step is an individual unit of work within a phase. A step holds the actual data (variables) and can produce a document. Steps allow you to:

Why Variables (CC Items) Exist

Each step has variables (called CC Items - Computation Context Items) that hold values. Some variables are entered manually by users, some are computed by AI prompts, and some are calculated by JavaScript functions. Variables can depend on each other, forming a computation graph. This is what makes the system powerful: you define inputs and the system produces outputs by walking the dependency chain automatically.

Variable types include:

The Campaign Hierarchy

flowchart TD
    Campaign["Campaign
'Summer Product Launch'"] Campaign --> P1["Phase 1
'Research'"] Campaign --> P2["Phase 2
'Content Creation'"] Campaign --> P3["Phase 3
'Review & Publish'"] P1 --> S1["Step: Market Analysis"] P1 --> S2["Step: Competitor Review"] P2 --> S3["Step: Blog Posts"] P2 --> S4["Step: Social Media"] P2 --> S5["Step: Landing Page"] P3 --> S6["Step: Final Review"] P3 --> S7["Step: Asset Export"] S3 --> V1["Var: audience_profile
(AI prompt)"] S3 --> V2["Var: blog_headline
(AI prompt, depends on V1)"] S3 --> V3["Var: blog_body
(AI prompt, depends on V1+V2)"] S3 --> V4["Var: word_count
(function)"] S3 --> V5["Var: blog_pdf
(asset - renders document)"] style Campaign fill:#EEEEFD,stroke:#623CEA style P1 fill:#F4FBFF,stroke:#22B5FF style P2 fill:#F4FBFF,stroke:#22B5FF style P3 fill:#F4FBFF,stroke:#22B5FF

The full hierarchy is: Campaign -> Phase -> Step -> Variable -> (produces) Asset

Why This Hierarchy Matters

BenefitHow the hierarchy enables it
Parallel workVariables without dependencies on each other run simultaneously across up to 30 threads per campaign
Selective recomputationRecompute a single variable, a step, a phase, or the entire campaign - your choice
Export / Import at any levelExport the entire campaign as ZIP, or export just one phase or one step independently
Independent editingOverride any variable's AI output with a manual value without affecting other variables
Template reuseThe same structure can be published as a template and cloned into new campaigns
Dependency trackingThe computation graph knows exactly which variables depend on which, enabling smart downstream reset

Computation Graph

When you trigger a computation, the system builds a dependency graph (DAG) of all variables, determines the optimal execution order via topological sort, and runs independent variables in parallel. AI-powered variables each get their own thread. The result is that a campaign with 100 variables might compute in minutes rather than hours, because many variables run simultaneously.

Campaign Lifecycle: 5 Phases

Every campaign goes through the same five phases, whether in the Admin Console or Customer App:

flowchart LR
    Create["1. CREATE
Clone from template
or start from scratch"] --> Configure["2. CONFIGURE
Set env vars, phases,
steps, variables"] Configure --> Compute["3. COMPUTE
Execute the DAG,
AI generates content"] Compute --> Iterate["4. ITERATE
Review, override,
re-compute"] Iterate --> Compute Iterate --> Publish["5. PUBLISH
Deploy to microsite,
export assets"] Configure --> Iterate
PhaseWhat happensKey concept
1. CreateStart a new campaign (empty, from template clone, or via import). The system creates the Campaign record and optionally deep-clones all phases, steps, and variables from a published template.Starting from a template saves time - the structure is pre-built
2. ConfigureSet up the campaign structure: add phases and steps, define variables (what inputs and AI prompts to use), configure environment variables (prompt templates, functions, shared config), assign document templates to steps, select the default AI model.This is design time - no AI calls yet
3. ComputeThe computation engine takes over: builds a dependency graph, resolves environment variables, then executes every variable in the correct order. AI prompts call LLM providers, functions run JavaScript, assets render document templates. Progress streams in real-time via WebSocket.This is where AI content is actually generated
4. IterateReview the computed results. Override any AI output with a manual value. Edit upstream variables and selectively recompute downstream dependents. Use the AI Chat interface to refine specific values conversationally. Patch AI results with human edits.You don't accept the first AI output - you refine it
5. PublishDeploy generated assets to the company microsite (S3 + CloudFront). Export the campaign as ZIP or push to Git. Assets go through an approval chain (Review -> Approve Content -> Approve Publication -> Publish).The final deliverables go live

Iterate is where most time is spent

The Compute-Iterate loop is the core workflow. Users typically compute, review results, override some values, recompute affected downstream variables, and repeat until the output quality is satisfactory. The system is designed to make this loop fast - you can recompute a single variable in seconds, not the whole campaign.

3. Templates & Blueprints

Campaign Types

Every campaign in the system has one of three types:

TypeDescriptionWho sees it
CampaignA working campaign created from a template or from scratchUsers with campaign access in the company
Draft TemplateA campaign being prepared as a reusable template (not yet available to others)Only admins/creators
Published TemplateA finalized template that others can use to start new campaignsAll users who can create campaigns

The Template Concept: Design Once, Start Many

The core idea behind templates is simple: a campaign designer builds a campaign structure once (phases, steps, variables, prompts, functions, document templates), publishes it as a template, and then any number of users can start new campaigns from it. Each new campaign gets its own independent copy of everything.

stateDiagram-v2
    [*] --> DraftTemplate : create as template
    [*] --> Campaign : create or start from template
    DraftTemplate --> PublishedTemplate : publish template
    PublishedTemplate --> DraftTemplate : unpublish
    PublishedTemplate --> Campaign : "Start Campaign" (clone + activate)
    Campaign --> Campaign : compute, edit, manage
    Campaign --> Archived : archive
    Archived --> Campaign : unarchive

    note right of PublishedTemplate
        Publishing resets all env items
        and computation items
    end note

    note right of Campaign
        "Start Campaign" deep-clones
        the entire template structure
    end note

"Start Campaign" = Deep Clone

When a user starts a campaign from a published template, the system creates a complete deep clone: all phases, steps, variables, environment items, i18n labels, and assets are copied. The new campaign gets its own independent copy of everything. What gets copied:

Publishing a template resets all data

When you publish a campaign as a template, all environment variables and computation items are reset to their initial state. This is intentional - templates are structures, not data. Any computed results in the template will be cleared. Do not publish if you need to preserve results.

Template changes do NOT propagate to live campaigns

Once a campaign is started from a template, it is fully independent. If you update the template later, existing campaigns are not affected. To propagate changes, you must use the Migration feature.

Template -> Campaign Relationship

flowchart TD
    Template["Published Template
(MCT)"] -->|"Start Campaign
(deep clone)"| C1["Campaign A"] Template -->|"Start Campaign"| C2["Campaign B"] Template -->|"Start Campaign"| C3["Campaign C"] Template -->|"Update template"| Template Template -.->|"NO auto-update"| C1 Template -.->|"NO auto-update"| C2 Template -.->|"NO auto-update"| C3 C1 -->|"mctId link
(read-only reference)"| Template style Template fill:#EEEEFD,stroke:#623CEA style C1 fill:#F4FBFF,stroke:#22B5FF style C2 fill:#F4FBFF,stroke:#22B5FF style C3 fill:#F4FBFF,stroke:#22B5FF

MCT (Market Campaign Template) - Git Integration

MCT is the system's approach to reusable campaign blueprints with version control. The workflow:

  1. A campaign designer builds a campaign structure (phases, steps, variables, prompts)
  2. They publish it as a Published Template - this is the MCT
  3. Users "Start" new campaigns from this MCT - each gets an independent deep clone
  4. The MCT can be versioned via Git integration - push/pull to a repository
  5. When the MCT is updated, existing campaigns are NOT affected (one-way clone)
  6. To propagate changes, use the Migration feature with field mapping

Git Push / Pull / Branch

flowchart LR
    MCT["Published Template
(MCT in DB)"] -->|"Git Push"| Repo["Git Repository
(directory structure)"] Repo -->|"Git Pull"| MCT MCT -->|"Start Campaign"| Live["Live Campaign
(independent clone)"] Repo -->|"Branch"| V2["New version branch"] V2 -->|"Merge + Pull"| MCT

Git stores the MCT as a directory tree: /phase_name/step_name/ with JSON files for each entity. On pull, the system does smart merging: detects renames, creates new items, updates existing ones.

Smart Merge on Git Pull

When pulling from Git, the system does not just overwrite. It finds phases by name first, then by sequence number. If a phase was renamed, it detects this and renames (moves) rather than creating a duplicate. Steps are matched the same way. This supports incremental template updates without data loss.

Migration: Propagating Template Updates to Live Campaigns

Since template changes do not auto-propagate, the Migration feature provides a controlled way to update existing campaigns:

  1. Analyze - the system compares source MCT with target campaign, matches by name, reports unmatched items
  2. Create mapping - a tab-delimited mapping file defines which source field maps to which target
  3. Choose what to copy: state, result, overrides, patches (each independently)
  4. Validate - preview mode shows what would change without persisting
  5. Execute - data transferred according to mapping

Variables tagged with the migration_carryover class keep their target value instead of being overwritten - useful for per-campaign customizations.

Template Matching via Classes

Document templates and steps use a class tagging system for matching. A document template is available for a step only if its classes overlap with the step's classes (or it falls back to default). This allows different steps to automatically use different document templates based on their tags.

Document Template Rendering

Document templates are the mechanism that turns raw computed data into formatted deliverables (HTML pages, PDF documents). The system supports three rendering engines:

EngineInputOutputBest for
XSLT (XSL)XML data + XSLT stylesheetHTML or PDF (via Apache FOP)Complex layouts, data-driven documents, PDF generation
FreeMarker (FTL)Variable map + FreeMarker templateHTMLDynamic content with conditionals, loops, macros
Static (STATIC)Key-value pairs + HTML with ${key} placeholdersHTMLSimple documents with minimal dynamic content

How rendering works

flowchart TD
    Trigger["Rendering triggered
(computation or preview)"] --> Load["Load template from DB"] Load --> Context["Build rendering context:
computed values, i18n, campaign metadata"] Context --> Engine{"Which engine?"} Engine -->|XSL| XSLT["XSLT transformation"] Engine -->|FTL| FM["FreeMarker processing"] Engine -->|STATIC| Static["Placeholder replacement"] XSLT --> Media{"Output format?"} Media -->|HTML| HTML["HTML output"] Media -->|PDF| FOP["Apache FOP -> PDF"] FM --> HTML Static --> HTML HTML --> Store["Store as asset"] FOP --> Store

Two rendering paths

The system has two fundamentally different ways to build the rendering context:

PathWhen usedData sourceTrade-off
Graph-basedDuring computation (Asset CC Item executing)In-memory graph nodes (live computation data)Always current, but only available during computation
Database-basedPreviews and standalone rendering (REST API)Database queries for CC ItemsMay be slightly stale if computation is in progress

Preview and actual rendering can show different results

If a computation is in progress, the graph-based path has the latest values (in memory) while the database-based path (used for previews) reads from DB. Some values may not be persisted yet. The preview will show stale data until the computation completes and values are written to the database.

HTML import and Figma conversion

Designers can upload HTML designs (including Figma exports) as ZIP packages. The system automatically:

  1. Extracts HTML and assets (images, CSS, fonts) from the ZIP
  2. Rewrites resource paths to cloud storage URIs
  3. Converts the HTML to an XSLT stylesheet (making it data-driven)
  4. Extracts referenced variable keys for template matching

This means designers can work in their preferred tools and the system converts their output into reusable, data-driven templates.

PDF generation: two approaches

FOP-based PDF - XSLT produces XSL-FO markup, processed by Apache FOP. Supports complex page layouts, embedded fonts, tables. Best for structured reports.
HTML-to-PDF - an external service converts the HTML output to PDF. Preserves CSS styling. Best for visually rich designs. Custom page sizes supported (A4 default, configurable in mm or inches).

4. Customer App - The 5-Step Wizard

The Customer App provides a guided experience for creating campaigns through 5 sequential steps:

flowchart TD
    Home["Home Page
(campaign cards)"] --> New["Step 1: Fundamentals"] New --> S2["Step 2: Target Audience"] S2 --> S3["Step 3: Content Strategy"] S3 --> S4["Step 4: Content Execution"] S4 --> S5["Step 5: Content Assets"] S5 --> Activate["Activate Campaign
(triggers heavy AI computation)"] Activate --> WS["Real-time WebSocket updates
(progress bar)"] WS --> Generated["View Campaign
(Generated state)"] Generated --> Edit45["Edit Steps 4-5
(field handlers for incremental AI updates)"] Generated --> Assets["View External/Internal Assets"] Generated --> Docs["View Campaign Foundation"]

The 5-Step Flow

StepWhat the user providesKey validationsComputation?
1. FundamentalsCampaign name, GTM Foundation (template), desired outcomes, timeframe, funnel stageName required + unique. GTM Foundation required.No
2. AudienceTarget personas (multi-select), segment, additional infoAt least 1 persona. Segment required.No
3. StrategyCampaign objective, point of view, content themes, messaging pillarsAll fields required.No
4. ExecutionStrategy description, content formats (multi-select), distribution channels, stage questionsAt least 1 format + channel.No
5. AssetsExternal content assets table (add/edit manually)At least 1 asset required before activation.Yes! Heavy AI computation triggered by "Activate"

What happens at "Activate Campaign"

This triggers a full campaign computation. The system builds a dependency graph of all variables, calls AI models to generate content, and produces campaign assets. Progress is streamed in real-time via WebSocket - the user sees a progress bar showing how many items are done vs. total. The state changes from "5/5" to "Generated" when complete.

Field Handlers (Incremental AI Updates)

After a campaign is generated (state = "Generated"), users can edit fields in Steps 4-5. When they change a field and click "Apply", a field handler fires:

  1. The updated field value is sent to the backend
  2. The backend identifies which downstream variables are affected
  3. Only those affected variables are recomputed (not the whole campaign)
  4. The step data auto-refreshes when computation completes

Only one field can be edited at a time

While a field handler is running, other fields are locked. The system prevents editing multiple fields simultaneously to avoid race conditions. Wait for the current field handler to complete before editing another field.

AI Assist

The Customer App includes an embedded AI chat feature called "AI Assist". When available on a step, users can open a chat panel, converse with the AI about their campaign content, and then push approved AI suggestions directly into campaign variables. AI Assist requires a chat-enabled AI model and step-level aiAssistParams configuration.

Dynamic Form System

The Customer App does NOT have hardcoded forms. Every form field comes from the backend as a schema:

  1. Backend defines each step's fields: type, validation, dependencies, handler
  2. Frontend's FormEngine renders them dynamically
  3. Each field can have an applyHandler that triggers backend computation when the user clicks "Apply"
  4. Field dependencies are declared: if field A changes, dependent field B is cleared and repopulated

This means the entire Customer App workflow can be changed by modifying backend templates without touching frontend code.

All supported field types (click to expand)
TypeRenders as
inputText/number input with placeholder
textareaMultiline text area
selectSingle dropdown
multiSelectMulti-select with Apply/Cancel buttons
singleSelectEditSingle select with inline edit
singleSelectCalendarDate picker dropdown
checkboxBoolean toggle
checkboxGroupMultiple checkboxes (funnel stages)
richTextWYSIWYG editor with formatting
json / jsonWithSelectJSON editor with validation
tableAsset table with add/edit/delete
textBlock / htmlDisplay-only content
dividerVisual separator
fieldGroupContainer with row/grid layout

Application State Machine

applicationState transitions:
  "1 / 5"  ->  "2 / 5"  ->  "3 / 5"  ->  "4 / 5"  ->  "5 / 5"  ->  "Generated"
      |           |           |           |           |              |
   (Step 1)   (Step 2)   (Step 3)   (Step 4)   (Step 5 +      (Read-only.
   Next btn    Next btn    Next btn    Next btn   Activate)    Steps 4-5 editable
                                                              via field handlers)

After "Generated", steps 1-3 become read-only. Steps 4-5 remain editable with field handlers that trigger incremental recomputation (not full campaign recomputation).

External vs Internal Assets

AspectExternal AssetsInternal Assets
What they areContent pieces for external distribution (blogs, whitepapers, social posts)Internal campaign documents (briefs, strategies)
Created byUser adds manually + AI generates during activationSystem generates from step templates
Editable?Yes (add, edit, delete, regenerate)No (read-only, system-generated)
StorageJSON field in CC itemCampaign steps + document templates
Grouped byAsset type / phaseStep / phase
ViewTable with columns: Type, Title, Persona, Core IdeaDocView embed (rendered document)

GTM Foundation vs Campaign Foundation

AspectGTM FoundationCampaign Foundation
ScopeOrganization-level go-to-market strategyCampaign-specific discovery and planning
Identified byPhase class = gtm-foundationPhases listed in campaign foundation data
ContentMarket strategy templates and frameworksCampaign briefs, audience analysis, positioning
Relationship to campaignProvides the template structureProvides the context for content generation
When usedSelected in Step 1 of wizardReferenced during AI content generation

5. AI / LLM Features

Full Technical Detail

5.1 Supported Providers

ProviderModelsCapabilitiesNotes
OpenAIGPT-4, GPT-4o, GPT-3.5, DALL-E 3Text, images, JSON schema, realtime WebSocket conversationsPrimary provider. Native JSON schema. Retries on 502 with 5s delay. Realtime API: gpt-4o-realtime-preview.
AnthropicClaude 3 Opus/Sonnet/Haiku, Claude 3.5Text, JSON schema (Claude 3+)Auto-corrects model names (underscores -> dashes).
Google GeminiGemini Pro, UltraText, JSON schemaGenerative AI API. Generation config support.
Google Vertex AIVariousTextRequires GCP project ID + service account.
PerplexityVariousSearch-augmented textBest for research-oriented prompts.
AWS BedrockVarious (Claude, Llama, etc.)TextAWS-hosted with standard retry mode.

5.2 Model Configuration

ParameterWhat it controlsTypical values
Model NameSpecific model identifiergpt-4, claude-3-sonnet-20240229
Max TokensMaximum output length1024 - 4096
TemperatureRandomness (0 = deterministic, 2 = very creative)0.0 - 2.0
Top PNucleus sampling diversity0.0 - 1.0
RPMRate limit (requests/minute)10 - 1000
Read TimeoutHow long to wait for response30 - 120 seconds
Retries on ErrorRetry count on failure1 - 5 (default: 3)
System DefaultUse when no model specifiedBoolean
Use in ChatAvailable in chat interfaceBoolean

Priority chain: Variable-specific model -> Campaign default model -> System default model.

5.3 Prompt Types

Text Prompts

A prompt template stored as an environment variable with placeholders:

Write a marketing headline for {product_name} targeting {audience}.
The tone should be {tone}. Maximum {max_words} words.

Placeholders are replaced with values from other variables. The completed prompt is sent to the AI model.

JSON Structured Output

Like text prompts but the AI must return valid JSON matching a defined schema. The system validates using JSON Schema draft-07. If invalid, retries with error feedback included.

Schema-Aware vs. Generic Providers

OpenAI and Google natively enforce JSON schemas in their API. For Anthropic, Perplexity, and Bedrock, the schema is embedded in the prompt text as instructions, and validation happens after the response.

Image Generation

DALL-E and other image models. Style options configurable. The generated image URL becomes the variable's value.

Session Prompts (Multi-turn Conversation)

Creates a persistent session with conversation history. Each message includes full history - token usage grows with each turn. Supports custom "bot instructions" (system prompt) per session.

5.4 Chat Interface

sequenceDiagram
    participant User
    participant Chat as Chat Interface
    participant System as Campaign Manager
    participant AI as AI Provider

    User->>Chat: Opens chat for a step
    Chat->>System: Load history and settings
    User->>Chat: Types message
    Chat->>System: Send message (async)
    System->>System: Build context (prompt + schema + history)
    System->>AI: Send formatted prompt
    AI-->>System: AI response
    alt JSON response invalid
        System->>AI: Retry with error feedback
        AI-->>System: Corrected response
    end
    System-->>Chat: Display response
    User->>Chat: Likes a suggested value
    Chat->>System: Save as Override (APPLIED)
    System->>System: Override CC Item value

Two modes: Document Chat (auto-populated with template keys) and Step Keys Chat (manual key selection).

Chat overrides are the bridge between conversation and campaign data: you chat with AI, refine output, then push approved values into campaign variables (status: Ready -> Applied or Canceled).

5.5 Rate Limiting & Key Pool

Warning: Blocking during high load

If many AI prompts run simultaneously with a low RPM, they queue up waiting for rate limit tokens. Large campaigns with many AI prompts take proportionally longer. Increase RPM or add more API keys for higher throughput.

5.6 Monitoring Metrics

MetricWhat it tracks
llm.durationAI call latency (SLOs: 2s, 5s, 10s, 20s, 30s, 60s; percentiles: p50/75/95/99)
llm.callsTotal calls by status (success/error), model, provider
llm.tokens.prompt/completionToken usage distribution
llm.request.retryRetried requests
chat.llm.*Chat-specific latency and token metrics

5.7 AI in Scripts

JavaScript functions can call AI models programmatically:

Argument count is validated against prompt template placeholders.

5.8 Analysis Agents (A2A Integration)

Campaign Manager integrates with an external Analysis Agents service - a set of specialized AI agents that analyze campaign data and provide insights. The agents run as a separate Python/FastAPI service and communicate via the A2A (Agent-to-Agent) protocol - Google's JSON-RPC 2.0 based standard.

Available Agents

AgentPurpose
execution_inspectorAnalyzes campaign execution results - checks provenance, validates computation outputs, identifies issues
campaign_plannerHelps plan campaign structure - suggests phases, steps, and variable configurations based on campaign goals
writing_orchestratorOrchestrates content generation - coordinates multiple writing tasks, ensures consistency across campaign materials

How it works

Agents can also be called from scripts

JavaScript function variables can call agents programmatically via the agentsUtils wrapper object, enabling automated agent-driven workflows within the computation graph.

6. Microsites & Publishing

Business Purpose

A microsite is a company-branded website for publishing campaign deliverables. Think of it as each company's content distribution hub:

URL Construction

https://{subdomain}.velocityengine.co/{siteContext}/{campaign.folder}/{phase.folder}/{step.folder}/{asset.file}

Example:
https://acme.velocityengine.co/content/c42/launch-phase/hero-content/assets/brochure.pdf

Each level (campaign, phase, step) has its own configurable folder name. Folders support placeholders like ${campaign.id}, ${phase.nameUrl}.

Multiple Campaigns, One Microsite

flowchart TD
    MS["acme.velocityengine.co
(company microsite)"] MS --> C1["/c42/
Campaign: Summer Sale"] MS --> C2["/c99/
Campaign: Product Launch"] MS --> C3["/c150/
Campaign: Brand Refresh"] C1 --> P1["/c42/research/..."] C1 --> P2["/c42/content/..."] C2 --> P3["/c99/phase1/..."] style MS fill:#EEEEFD,stroke:#623CEA

Path isolation ensures campaigns cannot overwrite each other's files. Each campaign has a unique folder (typically using campaign ID).

Microsite Infrastructure

sequenceDiagram
    participant Admin as Admin
    participant CM as Campaign Manager
    participant S3pub as Public S3 Storage
    participant S3ms as Microsite S3 Bucket
    participant CF as CloudFront CDN
    participant DNS as Route53 DNS

    Note over Admin,DNS: One-time microsite setup
    Admin->>CM: Configure microsite (subdomain, HTTPS)
    CM->>S3ms: Create S3 bucket (subdomain.velocityengine.io)
    CM->>DNS: Create DNS record
    opt HTTPS enabled
        CM->>CF: Create CloudFront distribution + SSL cert
        CM->>DNS: Create CNAME to CloudFront
    end

    Note over Admin,DNS: Per-asset deployment
    Admin->>CM: Deploy asset to microsite
    CM->>S3pub: Read asset file from public storage
    CM->>S3ms: Copy file to microsite bucket
    CM-->>Admin: URL: https://subdomain.velocityengine.io/path/asset.pdf

SFTP Direct Access

For power users and external tools, microsite users can upload files directly via SFTP:

Asset Approval Chain

stateDiagram-v2
    [*] --> Created : generated or uploaded
    Created --> ReadyForReview : submit for review
    ReadyForReview --> AssetApproved : reviewer approves content
    ReadyForReview --> NotPublished : rejected
    AssetApproved --> PublicationApproved : publisher approves
    AssetApproved --> NotPublished : publication denied
    PublicationApproved --> Published : deployed to microsite
    Published --> NotPublished : unpublished
    Created --> Error : generation failed

    note right of Published
        File copied from campaign storage
        to microsite S3 bucket.
        Public URL generated.
    end note

Auto-Publishing Stages

Publishing StageWhen assets are deployed
No deployNever auto-deployed
On demandEach asset deployed immediately after it is computed (one by one)
On execution done (all)All assets deployed after full computation completes
On execution done (not generated)Only non-generated assets deployed after computation

CloudFront & Caching

Only public storage assets can be deployed

Assets in private storage cannot be deployed to the microsite. If an asset references a file in private storage, deployment will fail with a "Private Asset" error. Move the file to public storage first.

7. Key Concepts Glossary

TermWhat it means
CampaignA project container holding all phases, steps, variables, and assets for a marketing initiative
PhaseA logical grouping of steps (e.g., "Research", "Content Creation", "Review")
StepA unit of work inside a phase, containing computation variables and optionally a document template
CC ItemComputation Context Item - a variable that holds a value (text, AI output, function result, image, etc.)
Environment VariableCampaign-level configuration: prompt templates, functions, shared data available across all steps
AssetA deliverable produced by the campaign (AI-generated document, uploaded file, or external link)
ComputationThe process of executing all variables to produce results via dependency graph
Computation GraphThe dependency network of all variables - determines execution order automatically
Document TemplateXSL, FreeMarker, or static HTML template that renders step data into a formatted document
CompanyAn organization/tenant - all data isolated per company
MicrositeA company-specific hosted website (S3 + optional CloudFront) for publishing campaign assets
ApplicationA campaign app configuration controlling which features are available in the Customer App
MCTMarket Campaign Template - a reusable campaign structure managed via Git
Permission GroupA named set of permissions (like a role) that can be assigned to users
OverrideA manually-entered value that replaces an AI-computed or function-computed result
Field HandlerA mechanism in the Customer App that triggers backend computation for a single field when it changes