# Ads Tracking Service Architecture / Kiến Trúc Dịch Vụ Theo Dõi Quảng Cáo

## Tổng Quan / Overview

```mermaid
graph TB
    subgraph "Tracking Sources"
        PIX[Website Pixel]
        SDK[Mobile SDK]
        API[Server-side API]
    end
    
    subgraph "ads-tracking-service"
        EVT[Event Ingestion]
        ATTR[Attribution Engine]
        STORE[(TimescaleDB)]
    end
    
    subgraph "Output"
        ANAL[ads-analytics]
        BILL[ads-billing]
    end
    
    PIX --> EVT
    SDK --> EVT
    API --> EVT
    
    EVT --> STORE
    EVT --> ATTR
    ATTR --> ANAL
    ATTR --> BILL
```

## Domain Aggregates

### TrackingPixelAggregate
- **TrackingPixel** (Root): Unique pixel per advertiser
- **PixelEvent**: PageView, AddToCart, Purchase, Lead

### ConversionAggregate
- **Conversion** (Root): Actual conversion event
- **ConversionValue**: Revenue amount
- **ConversionWindow**: 1-day, 7-day, 28-day

### AttributionAggregate
- **Attribution** (Root): Links conversion to ad
- **AttributionModel**: Last-click, First-click, Linear
- **TouchPoint**: Each ad interaction in journey

## Attribution Logic

```
┌─────────────────────────────────────────────────────────────────┐
│                     ATTRIBUTION FLOW                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  User Journey:                                                   │
│  ────────────                                                    │
│  Day 1: See Ad A (impression)                                    │
│  Day 3: Click Ad B                                               │
│  Day 5: Click Ad C                                               │
│  Day 6: Purchase $100                                            │
│                                                                  │
│  Attribution Models:                                             │
│  ──────────────────                                              │
│  Last-click:  Ad C = 100%                                        │
│  First-click: Ad B = 100%                                        │
│  Linear:      Ad B = 50%, Ad C = 50%                             │
│  Time-decay:  Ad B = 25%, Ad C = 75%                             │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

## Database Schema (TimescaleDB)

```sql
-- Pixels
CREATE TABLE tracking_pixels (
    id UUID PRIMARY KEY,
    advertiser_id UUID NOT NULL,
    pixel_code VARCHAR(50) UNIQUE,
    domain VARCHAR(255),
    created_at TIMESTAMP DEFAULT NOW()
);

-- Events (hypertable for time-series)
CREATE TABLE pixel_events (
    id UUID,
    pixel_id UUID REFERENCES tracking_pixels(id),
    event_type VARCHAR(50), -- 'PageView', 'AddToCart', 'Purchase'
    event_data JSONB,
    user_id VARCHAR(255),
    session_id VARCHAR(255),
    event_time TIMESTAMPTZ NOT NULL
);
SELECT create_hypertable('pixel_events', 'event_time');

-- Ad interactions (for attribution)
CREATE TABLE ad_interactions (
    id UUID PRIMARY KEY,
    user_id VARCHAR(255),
    ad_id UUID,
    campaign_id UUID,
    interaction_type VARCHAR(20), -- 'impression', 'click'
    interaction_time TIMESTAMPTZ NOT NULL
);

-- Conversions with attribution
CREATE TABLE conversions (
    id UUID PRIMARY KEY,
    pixel_event_id UUID,
    attributed_ad_id UUID,
    attributed_campaign_id UUID,
    attribution_model VARCHAR(50),
    conversion_value DECIMAL(18, 2),
    converted_at TIMESTAMPTZ
);
```

## Attribution Window Settings

| Setting | Click Window | View Window |
|---------|--------------|-------------|
| **7/1** (default) | 7 days | 1 day |
| **7/0** | 7 days | None |
| **28/1** | 28 days | 1 day |
| **1/1** | 1 day | 1 day |

## Pixel Integration Code

```html
<!-- Website Pixel -->
<script>
!function(g,o,od,go){
  g.ggq=g.ggq||[];
  var n=o.createElement('script');
  n.async=1;
  n.src='https://tracking.goodgo.com/pixel.js';
  o.body.appendChild(n)
}(window,document);

ggq('init', 'PX-XXXXXX');
ggq('track', 'PageView');
</script>

<!-- Track Purchase -->
<script>
ggq('track', 'Purchase', {
  value: 99.99,
  currency: 'VND',
  order_id: 'ORD-12345'
});
</script>
```

## Server-side Conversion API

```csharp
/// <summary>
/// EN: Server-side conversion tracking.
/// VI: Tracking conversion phía server.
/// </summary>
[HttpPost("events/server")]
public async Task<ActionResult> TrackServerEvent(
    [FromBody] ServerEventRequest request)
{
    // EN: More reliable than pixel (no ad blockers)
    // VI: Đáng tin cậy hơn pixel (không bị ad blocker)
    var result = await _mediator.Send(new TrackServerEventCommand
    {
        PixelId = request.PixelId,
        EventType = request.EventType,
        EventData = request.EventData,
        UserId = request.UserId, // hashed
        EventTime = request.EventTime
    });
    
    return Ok(result);
}
```

## Integration Events

```csharp
// Consume from ads-serving
public record AdImpressionTrackedEvent(
    Guid AdId, string UserId, string Placement, DateTime TrackedAt);

public record AdClickTrackedEvent(
    Guid AdId, string UserId, string DestinationUrl, DateTime TrackedAt);

// Publish to ads-analytics
public record ConversionAttributedEvent(
    Guid ConversionId, Guid AdId, Guid CampaignId,
    decimal ConversionValue, string AttributionModel);
```

## API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/v1/ads-tracking/pixels/{advertiserId}` | Get pixel code |
| `POST` | `/api/v1/ads-tracking/events` | Track pixel event |
| `POST` | `/api/v1/ads-tracking/events/server` | Server-side event |
| `GET` | `/api/v1/ads-tracking/conversions` | List conversions |
