CampaignOS

AI-Native Multi-Tenant Marketing Platform — Complete Technical Specification

Version 2.0 Status Draft for Review Updated April 2025 Owner Product & Engineering
Claude MCP Multi-tenant 14-week build $300–600/mo ops
01

Executive Summary

CampaignOS converts a website URL and advertising budget into a fully planned, copy-written, multi-platform ad campaign — and publishes it with explicit user consent via MCP connectors. Enter a URL and a budget. Get a complete, publishable campaign in under 5 minutes.

🏗️
Architecture Decision
Proceed with Claude MCP as the orchestration layer. Build Phase 1 (brand analysis + AI campaign generation) independently of ad connectors, validating the AI reasoning layer before integrating real ad spend. Use existing OAuth SDKs for connectors — not raw API calls.

Core Capabilities

CapabilityDescriptionAI Layer
Brand IntelligenceScrapes any URL; extracts design tokens, tone, colours, audience signalsClaude Vision
Persona Engine3–5 personas with platform affinity, messaging hooks, and budget splitsClaude API
Campaign GeneratorPer-persona × per-platform: headline, copy, CTA, targeting params, KPIsClaude API
Copy Variant Engine3 variants per campaign: Direct, Curiosity, Social Proof + live ad previewsClaude API
MCP ConnectorsPublishes to Google Ads, Meta, LinkedIn, X via OAuth. Consent-gated.MCP Server
Multi-tenant CoreFull workspace isolation per agency/brand. RBAC: Owner / Manager / ViewerPostgres RLS
Live AnalyticsUnified performance dashboard. Budget pacing alerts.Webhooks

Key Metrics

PlatformsAvg Setup TimeCampaign TypesMCP Tools
64 minutes1814

02

User Flow

01

Intake 30 seconds

Enter website URL, set monthly budget ($500–$50K), select target ad platforms.

02

Brand Analysis Claude Vision

Platform scrapes the URL and extracts industry, tone, brand colours, audience, USP, and keywords. Results stream live to the UI.

03

Persona Review Editable

4 AI-generated personas with messaging hooks and budget % splits. Toggle personas in/out or regenerate any individual one.

04

Campaign Generation AI Copy

Per-persona × per-platform campaigns: headline, body copy, CTA, targeting params, estimated CTR/CPC/reach.

05

Creatives + Preview 3 variants

Direct / Curiosity / Social Proof copy variants with live platform-accurate ad previews for Google, Meta, LinkedIn, and X.

06

Publish + Track Consent-gated

OAuth connect → Preview → Explicit "Authorize & Publish" → MCP tool call → Audit log entry → Live performance tracking.

UX Principles

  1. Transparency first — Always show what the AI extracted. Never black-box a step.
  2. Editability at every level — Personas, copy, budget splits, targeting are all editable inline.
  3. Granular regeneration — Regenerate at any level: this persona, this platform, this copy variant.
  4. Consent is explicit, never implied — OAuth connect and publish are two separate clicks, always.
  5. Draft before spend — Campaigns land as drafts on ad platforms. No money moves until the user confirms.

03

Architecture Approach Comparison

LangGraph + API
Alternative
Custom orchestration using LangGraph, calling Claude API directly alongside ad platform REST APIs.
Complexity
Flexibility
Dev Speed
Cost Eff.
Full control over every pipeline step
Explicit state machine for complex flows
More boilerplate per tool
State management grows non-linearly
Vercel AI SDK
Fastest Start
useChat / useCompletion hooks with server actions. Great for prototyping, not suited for background jobs.
Complexity
Flexibility
Dev Speed
Cost Eff.
Fastest time-to-demo
Built-in streaming and tool calls
Not for long-running background jobs
Harder to scale multi-tenant isolation
n8n / Make
No-code
Workflow automation with pre-built ad platform connectors. AI nodes available but shallow.
Complexity
Flexibility
Dev Speed
Cost Eff.
Pre-built ad platform connectors
Non-technical users can modify
AI reasoning is shallow — no brand analysis
No multi-tenant isolation
Expensive and inflexible at scale

Decision Matrix

CriterionClaude MCPLangGraphVercel AIn8n / Make
Multi-tenant isolation✅ Native RLS✅ Custom⚠️ Partial❌ Manual
AI reasoning depth✅ Full chain✅ Full chain⚠️ Medium❌ Shallow
Ad platform connectors✅ via MCP✅ via SDK⚠️ via SDK✅ Built-in
Background job support✅ BullMQ✅ Queue❌ Limited✅ Built-in
White-label ready⚠️
Consent / audit layer✅ Native✅ Custom⚠️
Time to MVP3–4 weeks4–6 weeks1–2 weeks1 week
Monthly infra cost$80–$200$100–$300$50–$150$200–$500
Vendor lock-inLowLowMediumHigh
IP ownershipFullFullFullPartial

04

Build vs Buy Analysis

14-Week Build Roadmap

PhaseTimelineDeliverables
Phase 1 — Core AI + IntakeWk 1–3Brand scraper (Puppeteer + Claude Vision), Persona generator, Campaign planner, Copy variant engine, Basic Next.js UI
Phase 2 — Multi-tenant + AuthWk 4–5NextAuth + workspace isolation, Postgres RLS policies, RBAC (Owner / Manager / Viewer), Client management UI
Phase 3 — MCP ConnectorsWk 6–8MCP Server setup, Google Ads OAuth + draft creation, Meta Marketing API, LinkedIn Ads API
Phase 4 — Publish + AnalyticsWk 9–11Consent-gate publish flow, Performance pull-back, Budget pacing alerts, Unified analytics dashboard
Phase 5 — Polish + ScaleWk 12–14White-label theming, API product layer, Monitoring + alerting, Documentation

Cost Breakdown

Line ItemEstimated Cost
Developer time (1 FT × 14 weeks)$28,000 – $42,000
Claude API (dev + staging)$200 – $400
Infra (Vercel + Supabase + Redis)$150 – $300
Ad platform dev accounts$0 (free tiers)
Total Build Investment$29,000 – $43,000
Monthly Running Cost$300 – $600 / month

Buy Landscape

ToolCategoryPrice / moWhat It CoversCritical Gap
JasperAI Copy$49–$125AI copy generationNo ad platform publishing
AdCreative.aiAI Copy$29–$149Ad creative generationNo persona engine or planning
Smartly.ioAI CopyCustomAd automation + publishingNo AI brand analysis, very expensive
n8n CloudAutomation$20–$50Workflow + connectorsNo AI reasoning layer, DIY everything
MakeAutomation$9–$29Visual workflowsShallow AI, no multi-tenant
HubSpot Mktg HubFull-stack$800–$3,200Full marketing suiteGeneric, not AI-native
Salesforce Mktg CloudFull-stackCustomEnterprise campaigns18-month impl, $100K+ contracts
Albert.aiFull-stackCustomAI ad managementBlack-box AI, no brand analysis
Why Not Buy
No single tool covers brand analysis + persona AI + ad publishing. Stitching tools costs $200–500/mo and still has major gaps. None provide multi-tenant workspace isolation out-of-the-box. The brand-to-campaign reasoning chain is the differentiator — buying eliminates the moat.
Why Build with Claude MCP
14 weeks to a fully shippable product with one developer. $300–600/mo to operate vs $500–1,000/mo for a stitched buy stack with gaps. You own the AI reasoning layer — an extensible MCP tool surface you keep growing. White-label to agencies and sell as SaaS: $30K build cost → $50K ARR breakeven.

05

System Architecture

Six-Layer Stack

01Frontend Layer
Next.js 14App RouterTailwind CSSIntake → Personas → Campaigns → Creatives → Publish → Analytics
02API + Auth Layer
NextAuthPostgres RLSRBACAudit LogRate Limiting
03Orchestration Layer
BullMQNode.jsscrape:jobpersona:jobcampaign:jobcreative:jobpublish:job
04Claude MCP Server
@modelcontextprotocol/sdkanalyze_websitegenerate_personasplan_campaigngenerate_ad_copypublish_campaignget_performance
05Ad Platform Connectors
OAuth 2.0Google Ads APIMeta Marketing APILinkedIn Ads APIX Ads APITikTok (Roadmap)
06Data Layer
SupabaseRedisS3WorkspacesCampaignsBrand SnapshotsPerformance

MCP Tool Definitions

Tool NameInput SchemaDescription
analyze_websiteurl, depthPuppeteer scrape + Claude Vision: extracts brand tokens, tone, palette, audience signals
generate_personasbrand_analysis, budget, platforms[]Produces 3–5 personas with platform affinity, budget split, messaging hook
plan_campaignpersonas[], budget, platforms[]Per-persona × per-platform campaign: headline, copy, CTA, targeting, KPIs
generate_ad_copycampaign_id, platform, personaWrites 3 copy variants: Direct / Curiosity / Social Proof
create_ad_draftcampaign_id, platformCreates draft on ad platform via SDK. No spend committed. Returns draft_id.
publish_campaigncampaign_id, platform, consentPublishes approved draft. require_consent: true by default. Writes audit record.
get_performancecampaign_id, date_rangePulls impressions, clicks, spend, conversions. Returns unified schema.
pause_campaigncampaign_id, platformPauses live campaign. Requires user confirmation.

Multi-tenant Data Model

Postgres Schema + RLS
-- Workspace hierarchy
workspaces    (id uuid PK, name, slug, plan, created_at)
  users       (id, workspace_id FK, role, email, oauth_tokens_enc)
  brands      (id, workspace_id FK, url, brand_snapshot jsonb)
    personas  (id, brand_id FK, name, traits jsonb, platform_affinity jsonb, budget_pct)
    campaigns (id, brand_id FK, status, budget, platform, flight_start, flight_end)
      ad_drafts   (id, campaign_id FK, variant, copy jsonb, targeting jsonb, consent_at)
      performance (id, campaign_id FK, date, impressions, clicks, spend, conversions)
  audit_log   (id, workspace_id, user_id, action, resource_id, metadata jsonb)

-- Row Level Security enforced at DB layer
CREATE POLICY workspace_isolation ON campaigns
  USING (workspace_id = current_setting('app.workspace_id')::uuid);

RBAC Permissions

ActionOwnerManagerViewer
Create workspace / invite users
Analyze brand
Generate personas & campaigns
Generate ad copy
Publish campaign
View campaigns & analytics
Manage billing

06

Campaign Generation — Deep Dive

The Four Claude Prompts

Prompt 1 — Brand Analysis

System Prompt
You are a brand strategist AI. When given a website URL/domain, infer likely
brand characteristics. Respond ONLY with a valid JSON object — no markdown,
no backticks, no explanation. Shape:
{
  "industry": "...",
  "tone":     "...",
  "colors":   ["#hex1", "#hex2"],
  "audience": "...",
  "usp":      "...",
  "keywords": ["k1", "k2", "k3"]
}

Prompt 2 — Persona Generation

System Prompt
You are an audience strategy expert. Respond ONLY with a JSON array.
Generate 4 personas with this shape:
[{
  "name":          "...",
  "age":           "25–35",
  "role":          "...",
  "platforms":    ["..."],
  "budgetPct":     25,          // must sum to 100
  "painPoint":    "...",
  "messagingHook": "...",
  "icon":          "◈"         // one of: ◈ ⬡ ◇ △
}]

Prompt 3 — Campaign Planning

System Prompt
You are a performance marketing strategist. Respond ONLY with a JSON array.
One item per persona×platform combination:
[{
  "persona":       "...",
  "platform":      "...",
  "format":        "...",
  "monthlyBudget": 500,
  "headline":      "...",  // max 40 chars
  "primaryCopy":   "...",  // max 90 chars
  "cta":           "...",  // max 20 chars
  "targeting": { "age": "...", "interests": ["..."] },
  "kpis": { "ctr": "2.1%", "cpc": "$1.20", "reach": "45K" }
}]

Prompt 4 — Copy Variant Writing

System Prompt
You are a world-class copywriter. Respond ONLY with a JSON object.
{
  "variants": [
    { "label": "Direct",       "headline": "...", "body": "...", "cta": "..." },
    { "label": "Curiosity",    "headline": "...", "body": "...", "cta": "..." },
    { "label": "Social Proof", "headline": "...", "body": "...", "cta": "..." }
  ]
}
Variants must be meaningfully different in angle and approach.
Headlines: max 40 chars. Body: max 90 chars. CTA: max 20 chars.

Copy Variant Strategy

VariantAngleBest ForExample Hook
DirectStates the benefit plainlyBottom-funnel, high-intent"Cut campaign setup from days to minutes"
CuriosityOpens a loop or asks a questionTop-funnel, cold audiences"What if your next campaign wrote itself?"
Social ProofLeverages numbers or trust signalsMid-funnel, consideration"10,000+ marketers already use this"

Platform Ad Format Specs

PlatformFormatHeadline LimitBody LimitCTA Options
Google SearchText ad30 chars × 390 chars × 2Custom
Meta FeedSingle image / carousel40 chars125 chars20 options
LinkedInSponsored Content70 chars150 chars18 options
X / TwitterPromoted Post70 chars280 charsCustom
TikTokIn-feed video80 charsN/A10 options

07

Tech Stack

ConcernChoiceRationale
FrontendNext.js 14 + TailwindApp Router, server components, streaming, edge-ready
AI OrchestrationClaude MCPNative tool calling, streaming, multi-step reasoning
Website ScrapingPuppeteer + Claude VisionScreenshot + structured extraction in one pass
Background JobsBullMQ + RedisReliable async queue for long-running AI jobs
AuthenticationNextAuth.jsSession management + per-platform OAuth 2.0
DatabaseSupabase + RLSRow-level security for multi-tenant isolation
Ad: Google Adsgoogle-ads-apiOfficial Node.js SDK, wraps gRPC API
Ad: Metameta-ads-sdkOfficial Marketing API client
Ad: LinkedInlinkedin-api-clientLinkedIn Marketing API v2
MonitoringSentry + DatadogError tracking + APM
DeploymentVercel + RailwayZero-config deploys, auto-scaling

08

Deployment Guide

🔑
Security: Never expose the Claude API key in the browser
All Claude API calls must be proxied through a Next.js API route. See the proxy route code below — this is mandatory before any public deployment.

Environment Variables

.env.local
# Claude API
ANTHROPIC_API_KEY=sk-ant-...

# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...

# Auth
NEXTAUTH_SECRET=your-secret-here
NEXTAUTH_URL=https://yourdomain.com

# Redis
REDIS_URL=redis://...

# Ad Platform OAuth
GOOGLE_ADS_CLIENT_ID=...
GOOGLE_ADS_CLIENT_SECRET=...
META_APP_ID=...
META_APP_SECRET=...
LINKEDIN_CLIENT_ID=...
LINKEDIN_CLIENT_SECRET=...

Claude API Proxy Route (Required)

app/api/claude/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { ratelimit } from '@/lib/redis';

export async function POST(req: NextRequest) {
  // 1. Auth check
  const session = await getServerSession(authOptions);
  if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });

  // 2. Rate limit per workspace
  const { success } = await ratelimit.limit(session.user.workspaceId);
  if (!success) return NextResponse.json({ error: 'Rate limited' }, { status: 429 });

  // 3. Proxy with server-side key — key never touches the browser
  const body = await req.json();
  const response = await fetch('https://api.anthropic.com/v1/messages', {
    method: 'POST',
    headers: {
      'Content-Type':      'application/json',
      'x-api-key':        process.env.ANTHROPIC_API_KEY!,
      'anthropic-version': '2023-06-01',
    },
    body: JSON.stringify(body),
  });
  return NextResponse.json(await response.json());
}

Vercel Deployment

Terminal
npm i -g vercel
vercel deploy
vercel env add ANTHROPIC_API_KEY
vercel env add NEXT_PUBLIC_SUPABASE_URL
# add remaining env vars, then promote
vercel --prod

09

MCP Server Implementation

Publish Tool — Consent Gate Pattern

tools/publish-campaign.ts
export const publishCampaign = {
  handler: async (args) => {
    // 1. Consent record MUST exist before any publish action
    const consent = await db.query(
      `SELECT * FROM audit_log
       WHERE resource_id = $1 AND action = 'consent_given'
       ORDER BY created_at DESC LIMIT 1`,
      [args.campaign_id]
    );
    if (!consent.rows.length) {
      return { error: 'CONSENT_REQUIRED',
        message: 'User must explicitly authorize before publishing.' };
    }

    // 2. Publish via platform SDK (not raw API call)
    const draft  = await db.getApprovedDraft(args.campaign_id);
    const result = await platformSDK[args.platform].publishDraft(draft.platform_draft_id);

    // 3. Write immutable audit record
    await db.query(
      `INSERT INTO audit_log (workspace_id, action, resource_id, metadata)
       VALUES ($1, 'campaign_published', $2, $3)`,
      [args.workspace_id, args.campaign_id, { platform: args.platform, result }]
    );
    return { success: true, platform_campaign_id: result.id, status: 'live' };
  }
};

10

Security & Compliance

AreaMechanismDetail
Tenant isolationPostgres RLSworkspace_id scoping at DB layer — app bugs cannot leak cross-tenant data
Session authNextAuthWorkspace membership validated on every API request
OAuth token storageAES-256 encryptionTokens encrypted at rest, per-workspace key
Consent gateAudit log checkpublish_campaign tool verifies consent record exists before any API call
Audit logAppend-only tableUsers cannot delete or modify consent/publish records
OAuth scopesMinimum privilegeRequest ads:write, never account:admin
API key securityServer-side proxyClaude API key never exposed in client-side code
Rate limitingUpstash RedisPer-workspace request limits on /api/claude proxy
Data retentionAuto-purge policyScreenshots purged after 30 days; PII never stored on CampaignOS
ComplianceSOC 2 Type II pathAchievable by Phase 5 via Supabase compliance tooling

11

Risks & Mitigations

RiskLikelihoodImpactMitigation
Ad platform API breaking changesMediumHighSDK abstraction layer; pin versions; monitor changelogs
Claude API latency on large brand analysisMediumMediumAsync job queue; streaming progress to UI
MCP ecosystem immaturityLowMediumWrap MCP tools with fallback REST calls
Multi-tenant data leak via app bugLowHighRLS enforced at DB layer; pen test before launch
OAuth token expiry causing publish failuresHighLowProactive token refresh; retry queue with alerts
Claude API cost overrun at scaleMediumMediumCache brand analyses 7 days; batch persona generation
Agency client ad overspendLowHighHard budget caps in draft creation; daily spend alerts
Wrong brand analysis for unknown domainMediumMediumAllow full manual override at every step

12

Next Steps

PhaseTimelineActions
ImmediateWeek 1Scaffold Next.js + Supabase + RLS. Implement analyze_website MCP tool. Build intake form with streaming brand analysis. Set up /api/claude proxy with auth + rate limiting.
Short-termWk 2–5Complete persona + campaign + copy variant MCP tools. Add workspace management and RBAC. Build strategy review UI with live ad previews.
Medium-termWk 6–11Integrate Google Ads and Meta SDKs as MCP connectors. Implement consent-gated publish flow with audit log. Build unified analytics dashboard.
LaunchWk 12–14White-label theming. API product surface. Security audit and penetration test. Documentation and onboarding flows.

13

Appendix

Glossary

TermDefinition
MCPModel Context Protocol — Anthropic's open protocol for connecting AI models to external tools and data sources
RLSRow Level Security — Postgres feature enforcing data access at the database layer, not the application layer
RBACRole-Based Access Control — permissions determined by user role (Owner / Manager / Viewer)
Ad DraftA campaign staged on the ad platform with no spend committed — for review before publish
Consent GateA mandatory user confirmation step before any action that incurs real ad spend
PersonaAI-generated audience segment with demographic, psychographic, and platform affinity data
Copy VariantOne of three ad copy versions (Direct / Curiosity / Social Proof) for the same campaign
WorkspaceA multi-tenant isolation unit — one workspace per agency or brand client

Supported Ad Platforms (v1.0)

PlatformAPIAuthDraftPerformance Pull
Google AdsGoogle Ads API v16OAuth 2.0
Meta (FB / IG)Meta Marketing API v19OAuth 2.0
LinkedInLinkedIn Marketing API v2OAuth 2.0
X (Twitter)X Ads API v12OAuth 1.0a / 2.0
TikTokTikTok for Business APIOAuth 2.0RoadmapRoadmap

Reference Links

  • Anthropic MCP Docs: https://modelcontextprotocol.io
  • Claude API Reference: https://docs.anthropic.com
  • Supabase RLS Guide: https://supabase.com/docs/guides/auth/row-level-security
  • Google Ads API: https://developers.google.com/google-ads/api/docs/start
  • Meta Marketing API: https://developers.facebook.com/docs/marketing-apis
  • LinkedIn Marketing API: https://learn.microsoft.com/en-us/linkedin/marketing/
  • NextAuth.js: https://next-auth.js.org
  • BullMQ: https://docs.bullmq.io