Files
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

6.3 KiB
Raw Permalink Blame History

Ads Analytics Service Architecture / Kiến Trúc Dịch Vụ Phân Tích Quảng Cáo

Tổng Quan / Overview

graph TB
    subgraph "Data Sources"
        SERV[ads-serving-service]
        TRACK[ads-tracking-service]
        MGR[ads-manager-service]
    end
    
    subgraph "ads-analytics-service"
        API[API Layer]
        INGEST[Ingestion Workers]
        AGG[Aggregation Engine]
        STORE[(ClickHouse/TimescaleDB)]
    end
    
    subgraph "Output"
        DASH[Dashboard API]
        REPORT[Report Generator]
        EXPORT[Export Service]
    end
    
    SERV -->|Impressions/Clicks| INGEST
    TRACK -->|Conversions| INGEST
    MGR -->|Campaign Metadata| API
    
    INGEST --> STORE
    STORE --> AGG
    AGG --> DASH
    AGG --> REPORT
    REPORT --> EXPORT

Domain Aggregates

MetricsAggregate

  • CampaignMetrics (Root): Impressions, Clicks, CTR, Spend
  • AdSetMetrics: Per-targeting performance
  • AdMetrics: Per-creative performance

ReportAggregate

  • Report (Root): Custom/scheduled reports
  • ReportSchedule: Daily, Weekly, Monthly
  • ReportExport: CSV, Excel, PDF formats

InsightAggregate

  • AudienceInsight: Demographics of reached users
  • PerformanceInsight: Optimization recommendations

Metrics Calculation

Metric Formula Description
CTR Clicks / Impressions Click-through rate
CPC Spend / Clicks Cost per click
CPM (Spend / Impressions) × 1000 Cost per mille
CPA Spend / Conversions Cost per acquisition
ROAS Revenue / Spend Return on ad spend
Frequency Impressions / Reach Avg views per user

Data Flow

┌─────────────────────────────────────────────────────────────────┐
│                     DATA PIPELINE                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Raw Events        Aggregation         Query                    │
│  (RabbitMQ)        (Background)        (API)                    │
│                                                                  │
│  Impression ──┐                                                  │
│               │    ┌──────────────┐    ┌──────────────┐         │
│  Click ───────┼───►│  Hourly      │───►│  Campaign    │         │
│               │    │  Rollup      │    │  Dashboard   │         │
│  Conversion ──┘    └──────────────┘    └──────────────┘         │
│                           │                                      │
│                           ▼                                      │
│                    ┌──────────────┐    ┌──────────────┐         │
│                    │  Daily       │───►│  Reports     │         │
│                    │  Summary     │    │  Export      │         │
│                    └──────────────┘    └──────────────┘         │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Database Schema (ClickHouse)

-- Raw events (high write throughput)
CREATE TABLE ad_events (
    event_id UUID,
    event_type Enum8('impression' = 1, 'click' = 2, 'conversion' = 3),
    ad_id UUID,
    campaign_id UUID,
    advertiser_id UUID,
    user_id String,
    cost Decimal(18, 6),
    event_time DateTime
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_time)
ORDER BY (campaign_id, event_time);

-- Hourly aggregates (fast queries)
CREATE MATERIALIZED VIEW campaign_metrics_hourly
ENGINE = SummingMergeTree()
PARTITION BY toYYYYMM(hour)
ORDER BY (campaign_id, hour)
AS SELECT
    campaign_id,
    toStartOfHour(event_time) AS hour,
    countIf(event_type = 'impression') AS impressions,
    countIf(event_type = 'click') AS clicks,
    countIf(event_type = 'conversion') AS conversions,
    sumIf(cost, event_type IN ('impression', 'click')) AS spend
FROM ad_events
GROUP BY campaign_id, hour;

API Endpoints

Metrics

Method Endpoint Description
GET /api/v1/ads-analytics/campaigns/{id}/metrics Campaign metrics
GET /api/v1/ads-analytics/campaigns/{id}/breakdown Breakdown by dimension

Reports

Method Endpoint Description
POST /api/v1/ads-analytics/reports Create custom report
POST /api/v1/ads-analytics/reports/schedule Schedule report
GET /api/v1/ads-analytics/reports/{id}/export Export report

Query Patterns

/// <summary>
/// EN: Get campaign metrics with breakdown.
/// VI: Lấy metrics chiến dịch với breakdown.
/// </summary>
public async Task<CampaignMetricsDto> GetMetricsAsync(
    Guid campaignId,
    DateRange dateRange,
    BreakdownDimension? breakdown = null)
{
    var query = _clickHouse.Query<MetricRow>(@"
        SELECT 
            campaign_id,
            sum(impressions) as impressions,
            sum(clicks) as clicks,
            sum(spend) as spend
        FROM campaign_metrics_hourly
        WHERE campaign_id = @campaignId
          AND hour BETWEEN @start AND @end
        GROUP BY campaign_id
    ");
    
    return await query.ExecuteAsync();
}

Integration

Service Integration Type Purpose
ads-serving-service RabbitMQ Consumer Impression/Click events
ads-tracking-service RabbitMQ Consumer Conversion events
ads-manager-service HTTP Client Campaign metadata