# Server-Side Tracking & Meta Conversions API (CAPI)

## Overview
BoonTrack mengimplementasikan sistem pelacakan hibrida (*hybrid tracking*) berstandar enterprise yang menggabungkan **Meta Pixel (Browser)** dan **Server-Side Meta Conversions API (CAPI)**. Arsitektur ini dirancang untuk mengatasi erosi data akibat ad-blocker, pembatasan privasi browser (iOS Intelligent Tracking Prevention / ITP), dan latensi jaringan, sekaligus menjaga kepatuhan privasi data.

---

## 1. Arsitektur Server-Side CAPI Dispatch

Pelacakan sisi server dijalankan secara asinkron dari layer backend BoonTrack langsung ke Meta Graph API endpoints (`https://graph.facebook.com/v19.0/{pixel_id}/events`).

```mermaid
flowchart LR
    subgraph Browser_Environment ["Browser Pembeli"]
        User["Pembeli"] -->|Aksi Checkout / Beli| Web["Next.js Storefront"]
        Web -->|1. Client Pixel Event (event_id)| MetaPixel["Meta Pixel (Browser)"]
        Web -->|2. HTTP POST Order| API["FastAPI Backend"]
    end

    subgraph Server_Environment ["BoonTrack Infrastructure"]
        API -->|3. Persist & Trigger Outbox| DB[("PostgreSQL")]
        DB -->|4. Relay Task| Redis[("Redis Queue")]
        Redis -->|5. Worker Dequeue| Worker["CAPI Background Dispatcher"]
    end

    subgraph Meta_Cloud ["Meta Advertising Platform"]
        Worker -->|6. Server-to-Server CAPI (event_id)| MetaCAPI["Meta Graph API (CAPI)"]
        MetaPixel -.->|Deduplikasi Otomatis (Match by event_id)| Deduplicator["Meta Event Deduplicator Engine"]
        MetaCAPI -.-> Deduplicator
    end
```

### Keunggulan Server-Side Dispatch
- **100% Delivery Reliability**: Pembayaran yang terjadi di latar belakang (misal: settlement QRIS via webhook) langsung memicu event `Purchase` server-side meskipun pembeli telah menutup jendela browser.
- **Bypass Ad-Blocker & ITP**: Request dikirim langsung dari server backend BoonTrack, kebal terhadap pemblokiran skrip di sisi browser.
- **Asynchronous Batching**: Dispatcher memproses event dalam antrean batch untuk menghemat kuota koneksi HTTP dan menjaga responsivitas API checkout.

---

## 2. Deduplikasi Event Browser vs Server via `event_id`

Saat menjalankan pelacakan ganda (Pixel di browser + CAPI di server), Meta membutuhkan identifikasi unik agar event yang sama tidak dihitung dua kali dalam dashboard Meta Ads Manager.

### Aturan Deduplikasi Deterministik
1. **Identitas Pasangan Event**:
   - `event_name` harus identik di kedua sisi (contoh: `Purchase` atau `InitiateCheckout`).
   - `event_id` harus memiliki nilai string yang sama persis di kedua sisi.
2. **Skema Penamaan `event_id`**:
   - Untuk event **Purchase**: Menggunakan Nomor Pesanan / Order ID unik (contoh: `ORD-20261008-8921X`).
   - Untuk event **InitiateCheckout**: Menggunakan UUID Checkout Session yang dibuat saat halaman kasir dibuka.
3. **Mekanisme Meta**:
   - Jika Meta menerima kedua event dalam kurun waktu 48 jam dengan `event_id` yang sama, Meta secara otomatis menggabungkannya menjadi satu event konversi tunggal dan memprioritaskan data dengan *Event Match Quality (EMQ)* tertinggi.

---

## 3. Normalisasi & Hashing Privasi SHA-256

Sebelum data pelanggan dikirimkan ke server Meta, parameter pengenal pribadi (*Personally Identifiable Information* / PII) wajib dinormalisasi dan di-hash menggunakan algoritma **SHA-256** sesuai standar keamanan data global dan regulasi **UU Pelindungan Data Pribadi (UU PDP)** Indonesia.

### Spesifikasi Normalisasi Parameter
| Parameter Meta | Sumber Data | Langkah Normalisasi Sebelum Hash | Contoh Output Hash (SHA-256) |
| :--- | :--- | :--- | :--- |
| `em` | Email Pelanggan | Trim spasi, konversi huruf kecil (*lowercase*), hapus karakter liar | `4f53cda18c2baa0c0354...` |
| `ph` | No. HP / WhatsApp | Hapus tanda `+`, `-`, spasi, dan pastikan kode negara (misal: `62812...`) | `9b73c647839356f12015...` |
| `fn` / `ln` | Nama Depan / Belakang | Trim spasi, konversi huruf kecil (*lowercase*) | `6d84f85e4e...` |

### Parameter Kontekstual Tanpa Hash
Beberapa parameter teknis dikirimkan apa adanya (tanpa di-hash) untuk memaksimalkan *Event Match Quality*:
- **`client_ip_address`**: Alamat IP asli pengguna yang diekstrak dari header Cloudflare (`CF-Connecting-IP`).
- **`client_user_agent`**: User-Agent browser pengguna.
- **`fbp`**: Nilai first-party cookie `_fbp` dari browser pengunjung.
- **`fbc`**: Nilai query parameter klik iklan `fbclid` yang disimpan dalam cookie `_fbc`.

### Contoh Implementasi Python di Backend
```python
import hashlib
import re

def normalize_and_hash(value: str) -> str:
    cleaned = value.strip().lower()
    return hashlib.sha256(cleaned.encode("utf-8")).hexdigest()

def normalize_phone_and_hash(phone: str) -> str:
    # Hapus semua karakter non-digit
    digits_only = re.sub(r"\D", "", phone)
    # Standarisasi format 08xx menjadi 628xx
    if digits_only.startswith("0"):
        digits_only = "62" + digits_only[1:]
    return hashlib.sha256(digits_only.encode("utf-8")).hexdigest()
```
