# 26 — Paid Ad Campaign Manager

**Status:** Design phase | **Priority:** High (marketing ROI, lead volume) | **Dependencies:** 00 (MASTER-PLAN), 03 (SELF-HOSTED-AI), 10 (AI-COPY-ENGINE), 15 (NEXTJS-WEB-APP)

**Completion Target:** 10 weeks | **Effort:** 380 hours | **Owner:** Marketing automation + performance optimization

---

## OVERVIEW

The Paid Ad Campaign Manager provides unified control over paid advertising across Google Ads, Meta (Facebook/Instagram), TikTok, and LinkedIn. It combines AI-powered ad copy generation, automated budget optimization, real-time performance tracking, and intelligent audience targeting — replacing manual campaign creation and disconnected reporting across platforms.

Luxury Presence's Ad Engine continuously optimizes campaigns with real-time budget allocation. Fogbreak integrates this into the operating system: agents create campaigns, AI generates copy, Fogbreak monitors performance hourly, shifts budget toward winners, pauses underperformers, and reports ROI per campaign.

**What It Replaces:** Manual Google Ads + Meta Ads Manager + LinkedIn Campaign Manager + disconnected spreadsheet ROI tracking.

**What It Adds:**
- Unified campaign creation wizard (all platforms from one dashboard)
- AI ad copy generation (Fair Housing audited, brand-compliant)
- Automated landing page generation (property-specific, high-converting)
- Budget optimization engine (AI hourly reallocation based on performance)
- Real-time metrics dashboard (impressions, clicks, CTR, CPC, CPL, conversions, ROI)
- Automated rules (pause if CPL > threshold, increase if ROAS > target, etc.)
- Audience management (geographic, demographic, interest-based, retargeting)
- Platform API integrations (Google Ads, Meta, TikTok, LinkedIn)
- Lead attribution (which campaign generated which CRM contact)
- Multi-currency + multi-market support

**Why It Matters:** Real estate is competition for attention. Listing agents need to drive qualified leads (sellers, buyers, investors) at scale. Most agents manually manage ads across 3-4 platforms, miss optimization opportunities, and can't measure ROI. Fogbreak centralizes ad creation, automates optimization, and proves ROI per property/campaign.

---

## DATABASE SCHEMA

### ad_campaigns

```sql
CREATE TABLE ad_campaigns (
  id INT AUTO_INCREMENT PRIMARY KEY,
  tenant_id INT,
  agent_id INT NOT NULL,  -- Agent who created campaign
  campaign_name VARCHAR(255) NOT NULL,
  campaign_description TEXT,
  objective ENUM('lead_generation', 'brand_awareness', 'listing_promotion', 'open_house', 'buyer_education', 'seller_education', 'investment_property', 'custom'),

  budget_daily DECIMAL(10, 2),  -- Daily spend limit
  budget_total DECIMAL(12, 2),  -- Total campaign budget (if fixed)
  budget_remaining DECIMAL(12, 2),  -- Remaining budget
  budget_type ENUM('daily', 'lifetime'),  -- Daily limit or total budget

  start_date DATE,
  end_date DATE,
  status ENUM('draft', 'pending_approval', 'active', 'paused', 'completed', 'cancelled'),

  platforms JSON,  -- ["google", "meta", "tiktok", "linkedin"]
  platform_ids JSON,  -- { "google": "campaign_id_123", "meta": "campaign_id_456", ... }

  target_audience_type ENUM('geographic', 'demographic', 'interest_based', 'retargeting', 'lookalike', 'custom'),
  target_locations VARCHAR(255),  -- e.g., "Carmel, CA; Monterey, CA; Pacific Grove, CA"
  target_zip_codes VARCHAR(255),  -- Comma-separated zip codes
  target_radius_miles INT,  -- e.g., 5 miles from listing

  target_age_min INT,  -- e.g., 25
  target_age_max INT,  -- e.g., 65
  target_income_range VARCHAR(100),  -- "$75k-150k", "$150k-500k", "500k+"
  target_homeowner BOOLEAN,  -- Only show to homeowners?
  target_behavior VARCHAR(255),  -- e.g., "home buyers, real estate interest"

  property_id INT,  -- Link to properties table (for listing campaigns)

  performance_impressions BIGINT DEFAULT 0,
  performance_clicks BIGINT DEFAULT 0,
  performance_ctr DECIMAL(5, 2) DEFAULT 0,  -- Click-through rate %
  performance_cpc DECIMAL(6, 2) DEFAULT 0,  -- Cost per click
  performance_conversions INT DEFAULT 0,
  performance_cpl DECIMAL(8, 2) DEFAULT 0,  -- Cost per lead
  performance_spend DECIMAL(12, 2) DEFAULT 0,  -- Total spend
  performance_roi DECIMAL(5, 2) DEFAULT 0,  -- Return on investment %

  last_metrics_sync TIMESTAMP,
  metrics_sync_frequency ENUM('hourly', 'daily', 'weekly') DEFAULT 'daily',

  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (tenant_id) REFERENCES tenants(id),
  FOREIGN KEY (agent_id) REFERENCES admins(id),
  FOREIGN KEY (property_id) REFERENCES properties(id),
  INDEX (tenant_id, agent_id),
  INDEX (status),
  INDEX (start_date),
  INDEX (objective)
);
```

### ad_creatives

```sql
CREATE TABLE ad_creatives (
  id INT AUTO_INCREMENT PRIMARY KEY,
  tenant_id INT,
  campaign_id INT NOT NULL,
  creative_type ENUM('headline', 'image_ad', 'video_ad', 'carousel_ad', 'search_ad', 'native_ad'),

  headline_primary VARCHAR(255),  -- Main headline
  headline_secondary VARCHAR(255),  -- Secondary headline (ads with multiple headlines)
  description_short VARCHAR(255),  -- 1-3 lines
  description_long TEXT,  -- Full copy
  cta_text VARCHAR(100),  -- "Get Your Free Valuation", "Schedule Showing", etc.

  image_url VARCHAR(500),  -- Property photo or generated image
  image_alt_text VARCHAR(255),

  video_url VARCHAR(500),  -- Video URL or YouTube ID
  video_duration_seconds INT,
  video_thumbnail_url VARCHAR(500),

  landing_page_url VARCHAR(500),  -- Link destination
  utm_source VARCHAR(100),  -- utm_source tracking
  utm_medium VARCHAR(100),  -- utm_medium tracking
  utm_campaign VARCHAR(100),  -- utm_campaign tracking

  is_ai_generated BOOLEAN DEFAULT FALSE,  -- Created by AI copy engine?
  ai_generation_prompt TEXT,  -- Original prompt used
  ai_generation_model VARCHAR(100),  -- "mistral_7b", "llama_70b", etc.

  fair_housing_audited BOOLEAN DEFAULT FALSE,
  fair_housing_issues TEXT,  -- If any issues found
  fair_housing_reviewed_by INT,  -- admin.id who reviewed

  performance_impressions BIGINT DEFAULT 0,
  performance_clicks BIGINT DEFAULT 0,
  performance_ctr DECIMAL(5, 2) DEFAULT 0,
  performance_cpc DECIMAL(6, 2) DEFAULT 0,
  performance_conversions INT DEFAULT 0,
  performance_spend DECIMAL(10, 2) DEFAULT 0,

  platform_status JSON,  -- { "google": "active", "meta": "approved", "tiktok": "pending", ... }

  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (tenant_id) REFERENCES tenants(id),
  FOREIGN KEY (campaign_id) REFERENCES ad_campaigns(id),
  INDEX (tenant_id, campaign_id),
  INDEX (is_ai_generated),
  INDEX (fair_housing_audited)
);
```

### ad_audiences

```sql
CREATE TABLE ad_audiences (
  id INT AUTO_INCREMENT PRIMARY KEY,
  tenant_id INT,
  campaign_id INT NOT NULL,
  audience_name VARCHAR(255),
  audience_type ENUM('saved_list', 'lookalike', 'interest_based', 'geographic', 'demographic', 'custom_pixel'),

  geographic_location VARCHAR(255),  -- "Carmel, CA 93921"
  geographic_radius_miles INT,

  demographic_age_min INT,
  demographic_age_max INT,
  demographic_gender ENUM('all', 'male', 'female'),
  demographic_income_range VARCHAR(100),

  interest_keywords VARCHAR(1000),  -- Comma-separated interests
  interest_behaviors VARCHAR(1000),  -- Real estate, home improvement, etc.

  saved_audience_id VARCHAR(500),  -- Platform-specific audience ID (e.g., Google Audience List ID)
  saved_audience_size INT,  -- Estimated audience size

  retargeting_pixel_id VARCHAR(500),  -- Pixel ID for retargeting
  retargeting_days INT,  -- Look back X days for pixel fires

  exclusion_lists TEXT,  -- People to exclude from targeting

  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (tenant_id) REFERENCES tenants(id),
  FOREIGN KEY (campaign_id) REFERENCES ad_campaigns(id),
  INDEX (tenant_id, campaign_id)
);
```

### ad_performance

```sql
CREATE TABLE ad_performance (
  id INT AUTO_INCREMENT PRIMARY KEY,
  tenant_id INT,
  campaign_id INT NOT NULL,
  creative_id INT,  -- NULL if campaign-level metrics
  platform VARCHAR(50),  -- 'google', 'meta', 'tiktok', 'linkedin'

  metric_date DATE,
  metric_hour INT,  -- 0-23 for hourly granularity (optional)

  impressions BIGINT,
  clicks BIGINT,
  conversions INT,
  spend DECIMAL(10, 2),
  revenue DECIMAL(12, 2),  -- If trackable (e.g., from CRM)

  ctr DECIMAL(5, 2),  -- (clicks / impressions) * 100
  cpc DECIMAL(6, 2),  -- spend / clicks
  cpa DECIMAL(8, 2),  -- spend / conversions
  roas DECIMAL(5, 2),  -- revenue / spend
  roi DECIMAL(5, 2),  -- (revenue - spend) / spend * 100

  synced_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (tenant_id) REFERENCES tenants(id),
  FOREIGN KEY (campaign_id) REFERENCES ad_campaigns(id),
  FOREIGN KEY (creative_id) REFERENCES ad_creatives(id),
  INDEX (tenant_id, campaign_id, metric_date),
  INDEX (platform, metric_date),
  INDEX (synced_at)
);
```

### ad_platform_accounts

```sql
CREATE TABLE ad_platform_accounts (
  id INT AUTO_INCREMENT PRIMARY KEY,
  tenant_id INT,
  platform VARCHAR(50),  -- 'google_ads', 'meta', 'tiktok', 'linkedin'

  account_id VARCHAR(255),  -- Platform account ID (e.g., Google Ads customer ID)
  account_name VARCHAR(255),  -- Display name
  account_email VARCHAR(255),  -- Email associated with account

  oauth_access_token VARCHAR(2000),  -- Encrypted
  oauth_refresh_token VARCHAR(2000),  -- Encrypted
  oauth_token_expires_at TIMESTAMP,

  api_key VARCHAR(1000),  -- For platforms that use API keys instead of OAuth

  connected_at TIMESTAMP,
  last_sync TIMESTAMP,
  sync_status ENUM('syncing', 'synced', 'error'),

  is_enabled BOOLEAN DEFAULT TRUE,

  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (tenant_id) REFERENCES tenants(id),
  UNIQUE KEY (tenant_id, platform),
  INDEX (platform)
);
```

### ad_landing_pages

```sql
CREATE TABLE ad_landing_pages (
  id INT AUTO_INCREMENT PRIMARY KEY,
  tenant_id INT,
  campaign_id INT,
  property_id INT,

  page_name VARCHAR(255),
  page_url VARCHAR(500),  -- e.g., fogbreak.io/lp/carmel_luxury_home

  template_type ENUM('property_valuation', 'listing_showcase', 'open_house', 'buyer_nurture', 'seller_education', 'custom'),

  headline VARCHAR(255),
  subheadline VARCHAR(255),
  cta_button_text VARCHAR(100),
  cta_button_action ENUM('lead_form', 'schedule_showing', 'view_more', 'download_pdf'),

  form_fields JSON,  -- ["name", "email", "phone", "property_interest"]

  hero_image_url VARCHAR(500),
  hero_video_url VARCHAR(500),

  page_content TEXT,  -- HTML or markdown of body content

  brand_id INT,  -- Which brand style (matthams, mcr, crc)

  ga4_tracking_id VARCHAR(100),  -- Google Analytics 4 measurement ID

  visits INT DEFAULT 0,
  form_submissions INT DEFAULT 0,
  conversion_rate DECIMAL(5, 2) DEFAULT 0,

  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (tenant_id) REFERENCES tenants(id),
  FOREIGN KEY (campaign_id) REFERENCES ad_campaigns(id),
  FOREIGN KEY (property_id) REFERENCES properties(id),
  INDEX (tenant_id, campaign_id)
);
```

### ad_rules

```sql
CREATE TABLE ad_rules (
  id INT AUTO_INCREMENT PRIMARY KEY,
  tenant_id INT,
  campaign_id INT NOT NULL,

  rule_name VARCHAR(255),
  rule_type ENUM('budget_shift', 'pause_campaign', 'increase_bid', 'notification', 'creative_swap'),

  trigger_metric ENUM('cpl', 'ctr', 'cpc', 'spend', 'conversions', 'roas', 'roi'),
  trigger_operator ENUM('greater_than', 'less_than', 'equals'),
  trigger_value DECIMAL(10, 2),  -- e.g., CPL > $50

  action VARCHAR(100),  -- e.g., "pause_campaign", "shift_budget_to_facebook", "notify_agent"
  action_value DECIMAL(10, 2),  -- e.g., shift 20% of budget

  is_enabled BOOLEAN DEFAULT TRUE,
  times_triggered INT DEFAULT 0,
  last_triggered_at TIMESTAMP,

  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (tenant_id) REFERENCES tenants(id),
  FOREIGN KEY (campaign_id) REFERENCES ad_campaigns(id),
  INDEX (tenant_id, campaign_id, is_enabled)
);
```

---

## API ENDPOINTS (api/campaigns.php)

### createCampaign

**POST /api/campaigns.php?action=createCampaign**

Create a new paid ad campaign. Wizard-based input: name, objective, budget, platforms, targeting.

```json
REQUEST:
{
  "agent_id": 12,
  "campaign_name": "Carmel Luxury Listing - Ocean Ave",
  "campaign_description": "Listing campaign for 123 Ocean Ave, targeting high-net-worth buyers",
  "objective": "listing_promotion",
  "budget_daily": 50,
  "budget_type": "daily",
  "start_date": "2026-04-01",
  "end_date": "2026-04-30",
  "platforms": ["google", "meta"],
  "target_locations": "Carmel, CA",
  "target_zip_codes": "93921, 93922",
  "target_radius_miles": 3,
  "target_age_min": 35,
  "target_age_max": 75,
  "target_income_range": "500k+",
  "target_homeowner": true,
  "property_id": 456
}

RESPONSE (success):
{
  "success": true,
  "data": {
    "campaign_id": 789,
    "campaign_name": "Carmel Luxury Listing - Ocean Ave",
    "status": "draft",
    "next_step": "Create ad creatives"
  }
}
```

### updateCampaign

**POST /api/campaigns.php?action=updateCampaign&campaign_id=789**

Update campaign settings (budget, dates, targeting, status). Can pause/resume.

```json
REQUEST:
{
  "budget_daily": 75,  // Increase budget
  "end_date": "2026-05-15",  // Extend campaign
  "status": "active"  // Launch campaign
}

RESPONSE (success):
{
  "success": true,
  "data": {
    "campaign_id": 789,
    "status": "active",
    "budget_daily": 75,
    "message": "Campaign launched on Google and Meta"
  }
}
```

### pauseCampaign

**POST /api/campaigns.php?action=pauseCampaign&campaign_id=789**

Pause a campaign (stops spending immediately).

```json
RESPONSE (success):
{
  "success": true,
  "data": {
    "campaign_id": 789,
    "status": "paused",
    "message": "Campaign paused on all platforms"
  }
}
```

### resumeCampaign

**POST /api/campaigns.php?action=resumeCampaign&campaign_id=789**

Resume a paused campaign.

```json
RESPONSE (success):
{
  "success": true,
  "data": {
    "campaign_id": 789,
    "status": "active",
    "message": "Campaign resumed"
  }
}
```

### getCampaignPerformance

**GET /api/campaigns.php?action=getCampaignPerformance&campaign_id=789&period=30**

Return campaign performance (last 30 days). Includes metrics per platform + total.

```json
RESPONSE (success):
{
  "success": true,
  "data": {
    "campaign_id": 789,
    "campaign_name": "Carmel Luxury Listing - Ocean Ave",
    "period_days": 30,
    "total_metrics": {
      "impressions": 45000,
      "clicks": 1250,
      "ctr": 2.78,
      "spend": 3750,
      "cpc": 3.00,
      "conversions": 45,
      "cpl": 83.33,
      "roi": 45
    },
    "by_platform": {
      "google": {
        "impressions": 25000,
        "clicks": 800,
        "ctr": 3.2,
        "spend": 2400,
        "cpc": 3.00,
        "conversions": 30,
        "cpl": 80
      },
      "meta": {
        "impressions": 20000,
        "clicks": 450,
        "ctr": 2.25,
        "spend": 1350,
        "cpc": 3.00,
        "conversions": 15,
        "cpl": 90
      }
    },
    "daily_trend": [
      { "date": "2026-03-30", "spend": 125, "clicks": 42, "conversions": 2 },
      ...
    ]
  }
}
```

### generateAdCopy

**POST /api/campaigns.php?action=generateAdCopy**

Use AI (from instruction 03/10) to generate ad headlines, descriptions, CTAs. Fair Housing audited.

```json
REQUEST:
{
  "campaign_id": 789,
  "property_details": {
    "address": "123 Ocean Ave, Carmel, CA 93921",
    "beds": 4,
    "baths": 2.5,
    "sqft": 3200,
    "features": ["Ocean view", "Fireplace", "Wine cellar", "Gated property"],
    "listing_price": 3100000
  },
  "tone": "luxury",
  "num_variations": 3
}

RESPONSE (success):
{
  "success": true,
  "data": {
    "campaign_id": 789,
    "generated_creatives": [
      {
        "headline_primary": "Oceanfront Luxury Living in Carmel",
        "headline_secondary": "Discover Your Dream Home with Coastal Views",
        "description": "Exquisite 4-bed oceanfront estate featuring panoramic views, wine cellar, and gated privacy.",
        "cta_text": "Schedule Your Private Showing",
        "is_ai_generated": true,
        "ai_model": "mistral_7b"
      },
      ...
    ],
    "fair_housing_status": "approved",
    "next_step": "Review creatives and select to add to campaign"
  }
}
```

### createAudience

**POST /api/campaigns.php?action=createAudience**

Create a targeting audience (saved segment, lookalike, interest-based, etc.).

```json
REQUEST:
{
  "campaign_id": 789,
  "audience_name": "Carmel High-Net-Worth Buyers",
  "audience_type": "demographic",
  "geographic_location": "Carmel, CA 93921",
  "geographic_radius_miles": 3,
  "demographic_age_min": 40,
  "demographic_age_max": 75,
  "demographic_income_range": "500k+",
  "demographic_gender": "all",
  "interest_keywords": "luxury homes, real estate investment, high-end properties"
}

RESPONSE (success):
{
  "success": true,
  "data": {
    "audience_id": 234,
    "audience_name": "Carmel High-Net-Worth Buyers",
    "estimated_size": 12500,
    "next_step": "Assign audience to campaign creatives"
  }
}
```

### syncPlatformMetrics

**POST /api/campaigns.php?action=syncPlatformMetrics**

Manually sync metrics from ad platforms. (Normally runs via cron hourly.)

```json
REQUEST:
{
  "campaign_id": 789,
  "platforms": ["google", "meta"]
}

RESPONSE (success):
{
  "success": true,
  "data": {
    "campaign_id": 789,
    "metrics_synced": {
      "google": { "status": "success", "metrics_updated": 5 },
      "meta": { "status": "success", "metrics_updated": 3 }
    },
    "total_spend": 3750,
    "total_conversions": 45
  }
}
```

### configureRules

**POST /api/campaigns.php?action=configureRules**

Create automated optimization rules (pause if CPL > threshold, shift budget, etc.).

```json
REQUEST:
{
  "campaign_id": 789,
  "rules": [
    {
      "rule_name": "Pause if CPL exceeds $100",
      "rule_type": "pause_campaign",
      "trigger_metric": "cpl",
      "trigger_operator": "greater_than",
      "trigger_value": 100,
      "is_enabled": true
    },
    {
      "rule_name": "Increase budget if ROAS > 3",
      "rule_type": "budget_shift",
      "trigger_metric": "roas",
      "trigger_operator": "greater_than",
      "trigger_value": 3,
      "action": "increase_budget",
      "action_value": 10,  // Increase by 10%
      "is_enabled": true
    }
  ]
}

RESPONSE (success):
{
  "success": true,
  "data": {
    "campaign_id": 789,
    "rules_created": 2,
    "rules_active": 2
  }
}
```

### getROIDashboard

**GET /api/campaigns.php?action=getROIDashboard&agent_id=12&period=30**

Return ROI dashboard for agent. All campaigns with spend, conversions, ROI, trend.

```json
RESPONSE (success):
{
  "success": true,
  "data": {
    "agent_id": 12,
    "period_days": 30,
    "campaigns": [
      {
        "campaign_id": 789,
        "campaign_name": "Carmel Luxury Listing - Ocean Ave",
        "total_spend": 3750,
        "conversions": 45,
        "cpl": 83.33,
        "estimated_revenue": 135000,  // Assumes avg listing price
        "roi": 3500,  // (revenue - spend) / spend * 100
        "status": "active"
      },
      ...
    ],
    "summary": {
      "total_spend": 12500,
      "total_conversions": 178,
      "avg_cpl": 70.22,
      "total_estimated_revenue": 534000,
      "blended_roi": 4172
    },
    "trends": [
      { "week": "2026-03-23", "spend": 3200, "conversions": 42, "roi": 2800 },
      ...
    ]
  }
}
```

### connectPlatform

**POST /api/campaigns.php?action=connectPlatform**

OAuth flow to connect ad platform (Google Ads, Meta, TikTok, LinkedIn).

```json
REQUEST:
{
  "platform": "google_ads",
  "redirect_uri": "https://fogbreak.io/api/campaigns.php?action=handleOAuthCallback"
}

RESPONSE (success):
{
  "success": true,
  "data": {
    "oauth_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&scope=..."
  }
}
```

### generateLandingPage

**POST /api/campaigns.php?action=generateLandingPage**

Generate a high-converting landing page for campaign (property listing, buyer nurture, etc.).

```json
REQUEST:
{
  "campaign_id": 789,
  "template_type": "listing_showcase",
  "property_id": 456,
  "headline": "Oceanfront Luxury Living in Carmel",
  "cta_button_text": "Schedule Private Showing",
  "cta_button_action": "schedule_showing"
}

RESPONSE (success):
{
  "success": true,
  "data": {
    "landing_page_id": 567,
    "url": "https://fogbreak.io/lp/carmel_ocean_ave_2026",
    "preview_url": "https://fogbreak.io/lp/carmel_ocean_ave_2026?preview=1",
    "ga4_tracking_id": "G-XXXXXXXXXXXX"
  }
}
```

---

## IMPLEMENTATION STEPS

### Phase 1: Platform Integrations (Weeks 1-3)

1. **Google Ads API (v17)**:
   - Implement OAuth 2.0 authentication
   - Build campaign creation (GoogleAdsService)
   - Build ad group creation (AdGroupService)
   - Build responsive search ads (AdService)
   - Build audience management (AudienceService)
   - Implement metrics sync (GoogleAdsService.search with metrics)
   - Rate limit: 10,000 queries/day free tier, 10k+ premium
   - Store oauth_access_token + oauth_refresh_token in ad_platform_accounts

2. **Meta Marketing API (v21)**:
   - Implement OAuth 2.0 (Facebook Login)
   - Build campaign creation (POST /adaccount/campaigns)
   - Build ad set creation (budget, targeting)
   - Build creative/ad creation (images, copy)
   - Build insights API (GET /insights with breakdowns by day/platform)
   - Rate limit: 5,000 calls/hour
   - Support Facebook + Instagram ads simultaneously

3. **TikTok Marketing API**:
   - Implement OAuth 2.0
   - Build campaign creation
   - Build ad group creation (ad placements, targeting)
   - Build creative management
   - Build reporting (metrics API)
   - Rate limit: 1,000 requests/hour

4. **LinkedIn Campaign Manager API**:
   - Implement OAuth 2.0
   - Build account + campaign management
   - Build audience targeting (job title, company, etc.)
   - Build ad creative management
   - Build analytics (impressions, clicks, conversions)
   - Rate limit: 600 requests/minute

5. **Error handling**:
   - If API call fails, mark campaign as "sync_error"
   - Retry with exponential backoff
   - Alert agent if platform sync fails for >2 hours

### Phase 2: Campaign Creation Wizard (Weeks 2-4)

1. **Build Next.js campaign builder**:
   - Step 1: Campaign details (name, objective, budget, dates)
   - Step 2: Platform selection (Google, Meta, TikTok, LinkedIn)
   - Step 3: Targeting (location, demographics, interests, behaviors)
   - Step 4: Property selection (if listing campaign)
   - Step 5: Review and launch

2. **Implement validation**:
   - Budget > $1/day
   - Start date = today or future
   - End date > start date
   - At least one platform selected
   - Targeting not empty

3. **Build OAuth flow**:
   - First time: Redirect to platform OAuth login (Google/Meta/TikTok/LinkedIn)
   - Store tokens in ad_platform_accounts
   - Subsequent campaigns: Use stored credentials

4. **Test end-to-end**: Create campaign in UI → verify created on Google Ads + Meta.

### Phase 3: AI Ad Copy Generation (Weeks 3-5)

1. **Integrate with instruction 03 (Self-Hosted AI)**:
   - Use Mistral 7B for ad copy generation
   - Prompt: "Generate 3 variations of Google Ads copy for [property details]. Tone: [luxury/professional/casual]. Include headlines, descriptions, CTAs."

2. **Implement Fair Housing audit**:
   - Query AI output against Fair Housing policy (no discrimination by protected class, no exclusionary language)
   - Flag copy if any Fair Housing issues detected
   - Require human review before publication

3. **Build variation generator**:
   - Generate N variations (typically 3-5)
   - Each variation different tone/angle
   - Agent can edit before adding to campaign

4. **Store creatives in ad_creatives table**:
   - headline_primary, headline_secondary, description, cta_text
   - Mark is_ai_generated = true
   - Store ai_generation_prompt + ai_generation_model

### Phase 4: Audience Management (Weeks 4-5)

1. **Build audience creation UI**:
   - Geographic: Address/zip + radius
   - Demographic: Age, income, gender, homeowner status
   - Interest-based: Keywords + behaviors
   - Retargeting: Website pixel + lookback window
   - Lookalike: Based on CRM customer list

2. **Implement platform audience syncing**:
   - Create audience on Google (Customer Match list, Custom intent audience, etc.)
   - Create audience on Meta (Custom Audience via email upload, Lookalike)
   - Create audience on TikTok (Custom audience, Lookalike)
   - Store platform audience_id for reuse

3. **Build saved audiences**:
   - Save frequently-used audiences (e.g., "Carmel High-Net-Worth")
   - Reuse across campaigns

### Phase 5: Landing Page Generation (Weeks 5-6)

1. **Build landing page templates** (Next.js):
   - Property showcase: Hero image, property details, CTA for showing
   - Buyer education: Market trends, tips, lead form
   - Seller education: Home valuation, market analysis, lead form
   - Open house: Event details, RSVP form, property gallery

2. **Implement personalization**:
   - Use campaign/property data to populate copy
   - Use brand colors from tenant config
   - Generate unique URL per campaign (fogbreak.io/lp/[campaign_slug])

3. **Build form integration**:
   - Landing page form → CRM client creation
   - Track form submissions (conversions)
   - UTM tracking (utm_source=google_ads, utm_campaign=carmel_listing, etc.)

4. **Implement analytics**:
   - GA4 tracking ID per landing page
   - Track visits, form submissions, conversion rate
   - Display in campaign dashboard

### Phase 6: Performance Metrics & Optimization (Weeks 6-8)

1. **Build metrics sync** (from all platforms):
   - Query Google Ads API for impressions, clicks, conversions, spend
   - Query Meta API for same
   - Query TikTok API for same
   - Query LinkedIn API for same
   - Aggregate into ad_performance table by campaign + creative + platform

2. **Implement metric calculations**:
   - CTR = (clicks / impressions) * 100
   - CPC = spend / clicks
   - CPA/CPL = spend / conversions
   - ROAS = revenue / spend (if trackable from CRM)
   - ROI = (revenue - spend) / spend * 100

3. **Build optimization engine**:
   - Monitor performance hourly
   - If ROAS > target (e.g., 3.0), increase budget by 10%
   - If ROAS < threshold (e.g., 1.5), decrease budget by 10%
   - If CPL > threshold (e.g., $100), pause campaign
   - If CTR > avg + 20%, increase bid
   - Implement using scheduled cron job (ad_optimization)

4. **Build budget allocation logic**:
   - Allocate daily budget across platforms based on yesterday's ROAS
   - Higher ROAS platforms get larger share of budget
   - Minimum spend per platform = $5/day (to maintain data collection)

### Phase 7: Rules & Automation (Week 7)

1. **Build rules engine**:
   - Define rule conditions: metric + operator + threshold
   - Define actions: pause, increase budget, shift budget, notify agent
   - Store in ad_rules table

2. **Implement rule execution** (cron job, hourly):
   - For each enabled rule, check if trigger conditions met
   - Execute action if met
   - Log to cron_log with details

3. **Build rule templates**:
   - "Pause if CPL exceeds $X"
   - "Increase budget if ROAS > X"
   - "Pause creative if CTR drops below X%"
   - "Notify agent if spend > $X today"

### Phase 8: ROI Tracking & Reporting (Weeks 8-9)

1. **Implement lead attribution**:
   - Track which campaign/creative generated each CRM client
   - Store campaign_source + utm_campaign in clients table
   - Calculate revenue per campaign (based on deals closed from clients)

2. **Build ROI dashboard**:
   - Display spend per campaign
   - Display conversions per campaign
   - Display CPL (cost per lead)
   - Display estimated revenue (based on avg deal value)
   - Display ROI = (revenue - spend) / spend * 100
   - Trend over time

3. **Build reporting**:
   - Weekly email: Top performing campaigns, CPL trends, ROI summary
   - Monthly report: Detailed breakdown by platform, creative, audience

### Phase 9: Integration (Week 10)

1. **Integrate with instruction 10 (AI Copy Engine)**:
   - Use AI copy module for ad headline + description generation
   - Link to Fair Housing audit in email.php

2. **Integrate with instruction 15 (Next.js)**:
   - Deploy campaign builder at fogbreak.io/campaigns/builder
   - Deploy landing page system

3. **Integrate with drips.php**:
   - Auto-enroll campaign leads into nurture drips
   - Trigger based on campaign objective (seller nurture, buyer nurture, etc.)

---

## CRON JOBS (api/cron.php)

### ad_metrics_sync

**Runs:** Every hour | **Duration:** ~5 minutes | **Auth:** API key

```php
// For each ad_campaign with status='active' and last_metrics_sync < 1 hour ago:
//   1. Query Google Ads API for metrics (impressions, clicks, conversions, spend)
//   2. Query Meta API for metrics
//   3. Query TikTok API for metrics
//   4. Query LinkedIn API for metrics
//   5. Insert rows into ad_performance table
//   6. Update ad_campaigns with latest metrics (performance_impressions, performance_clicks, etc.)
//   7. Update last_metrics_sync = NOW()
// Return summary: {campaigns_synced: N, metrics_inserted: M, errors: [...]}
```

### ad_optimization

**Runs:** Every 4 hours | **Duration:** ~10 minutes | **Auth:** API key

```php
// For each ad_campaign with status='active':
//   1. Calculate average ROAS for last 7 days
//   2. Calculate average ROAS for yesterday
//   3. If yesterday_roas > 3.0 AND budget_used < budget_daily:
//        -> Increase budget by 10%
//   4. If yesterday_roas < 1.5 AND budget_used > 0:
//        -> Decrease budget by 10%
//   5. If cpl > threshold from rules:
//        -> Execute rule action
//   6. Update campaign budget in all platform APIs
//   7. Log optimization in cron_log
// Return summary: {budgets_adjusted: N, platforms_updated: M}
```

### ad_rule_engine

**Runs:** Every hour | **Duration:** ~5 minutes | **Auth:** API key

```php
// For each ad_rule with is_enabled=true:
//   1. Get latest metric (from ad_performance, most recent)
//   2. Check if trigger_metric meets condition (trigger_operator + trigger_value)
//   3. If condition met:
//        -> Execute rule action (pause_campaign, notify_agent, shift_budget)
//        -> Update rule (times_triggered++, last_triggered_at=NOW())
//        -> Log to cron_log
// Return summary: {rules_evaluated: N, rules_triggered: K, actions_executed: M}
```

---

## TESTING CRITERIA

### Unit Tests

1. **Campaign creation**:
   - Test with valid inputs (name, budget, platforms, dates)
   - Test with invalid budget (<$1)
   - Test with end_date before start_date
   - Verify campaign created in ad_campaigns table
   - Verify platform_ids populated (platform account linked)

2. **Ad copy generation**:
   - Test with property details
   - Verify 3+ variations generated
   - Verify Fair Housing audit passes/flags appropriately
   - Verify copy includes property address + key features

3. **Audience creation**:
   - Test geographic audience (address + radius)
   - Test demographic audience (age, income)
   - Verify audience created on platform (saved_audience_id populated)
   - Verify estimated audience size > 0

4. **Metrics calculations**:
   - Test CTR = (clicks / impressions) * 100
   - Test CPC = spend / clicks
   - Test CPA = spend / conversions
   - Verify no division by zero errors

### Integration Tests

1. **End-to-end campaign flow**:
   - Create campaign in UI
   - Select platforms (Google + Meta)
   - Generate ad copy
   - Create audience
   - Generate landing page
   - Verify campaign synced to Google Ads + Meta Ads Manager
   - Verify landing page accessible

2. **Metrics sync**:
   - Create campaign on Google Ads + Meta
   - Wait for cron_metrics_sync to run
   - Verify ad_performance populated with metrics
   - Verify ad_campaigns updated with total metrics

3. **Budget optimization**:
   - Create campaign with $50/day budget
   - Simulate high ROAS (3.0+) yesterday
   - Run ad_optimization cron
   - Verify budget increased to ~$55/day

4. **Rules engine**:
   - Create campaign with rule: "Pause if CPL > $100"
   - Simulate CPL = $120
   - Run ad_rule_engine cron
   - Verify campaign paused (status='paused')

5. **Lead attribution**:
   - Create campaign
   - Lead fills out landing page form
   - Verify client created in CRM with campaign_source
   - Verify attributed to correct campaign in getROIDashboard

### Performance Tests

1. **API sync speed**: 10 campaigns synced from 4 platforms in <5 minutes
2. **Optimization speed**: Recalculate budget for 50 campaigns in <2 minutes
3. **Rules evaluation**: Check 100+ rules per hour
4. **Landing page load time**: <2 seconds on 3G

### Security Tests

1. **OAuth token security**: Access tokens encrypted in database
2. **Platform API credentials**: Never logged or exposed in UI
3. **Campaign isolation**: Agent can only see/edit own campaigns
4. **Admin-only actions**: configureRules, adjustBudgetManually require admin role
5. **Fair Housing audit**: No ad copy published without passing audit

---

## ESTIMATED COSTS

- **Google Ads API**: Free (use existing account)
- **Meta Marketing API**: Free (use existing account)
- **TikTok Marketing API**: Free (use existing account)
- **LinkedIn Campaign Manager API**: Free (use existing account)
- **Ad spend**: Varies by tenant, typically $1,000-$5,000/month per agent
- **Google Analytics 4**: Free
- **Landing page hosting**: Included (Next.js on existing infrastructure)

**Typical tenant cost**: $0 API costs + ad spend management overhead

---

## DEPLOYMENT CHECKLIST

- [ ] Implement Google Ads API integration
- [ ] Implement Meta Marketing API integration
- [ ] Implement TikTok Marketing API integration
- [ ] Implement LinkedIn Campaign Manager API integration
- [ ] Build campaign creation wizard (Next.js)
- [ ] Build OAuth flow for platform authentication
- [ ] Integrate with AI copy engine (instruction 10)
- [ ] Implement Fair Housing audit for ad copy
- [ ] Build audience management UI
- [ ] Build landing page generator
- [ ] Implement metrics sync from all platforms
- [ ] Test metrics accuracy (backtest 10+ campaigns)
- [ ] Build budget optimization engine
- [ ] Build rules engine + rule templates
- [ ] Build ROI dashboard + reporting
- [ ] Test lead attribution flow
- [ ] Add cron jobs (metrics_sync, optimization, rule_engine)
- [ ] Integration test end-to-end flow
- [ ] Load test with 100+ campaigns
- [ ] Security audit (OAuth tokens, admin access, Fair Housing)
- [ ] Document API in ARCHITECTURE.html
- [ ] User documentation + training
- [ ] Deploy to Bluehost

---

## FUTURE ENHANCEMENTS

- **AI creative testing**: Automatically test variations and pause underperformers
- **Predictive budget allocation**: Use ML to predict which platforms/creatives will win before spending
- **Cross-platform audience sync**: Share audiences across Google, Meta, TikTok
- **Dynamic pricing**: Adjust bids based on competition, time of day, day of week
- **Conversion value tracking**: Track actual deal size from CRM, optimize for revenue (not just conversions)
- **Video ad generation**: Auto-generate short-form video ads (instruction 13 integration)
- **A/B testing automation**: Suggest test hypotheses, run tests, pause losers
- **Attribution modeling**: Multi-touch attribution (which touchpoint actually drove conversion)

---

**Owner:** Kean | **Reviewed by:** Architecture working group | **Next:** Deploy to production + market rollout
