# Pounce Yield - Complete Setup Guide

This guide covers the complete setup of the Yield/Intent Routing feature.

## Overview

Pounce Yield allows users to monetize their parked domains by:
1. Detecting user intent from domain names (e.g., "zahnarzt-zuerich.ch" → Medical/Dental)
2. Routing visitors to relevant affiliate partners
3. Tracking clicks, leads, and sales
4. Splitting revenue 70/30 (user/Pounce)

## Architecture

```
┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│   User Domain   │────▶│  Pounce Yield    │────▶│ Affiliate       │
│  (DNS → Pounce) │     │  Routing Engine  │     │ Partner         │
└─────────────────┘     └──────────────────┘     └─────────────────┘
                               │
                               ▼
                        ┌──────────────────┐
                        │   Transaction    │
                        │   Tracking       │
                        └──────────────────┘
```

## Setup Steps

### 1. Database Setup

The yield tables are created automatically on startup. To apply migrations to an existing database:

```bash
cd backend
python -c "from app.database import init_db; import asyncio; asyncio.run(init_db())"
```

### 2. Seed Affiliate Partners

Populate the affiliate partners with default Swiss/German partners:

```bash
cd backend
python scripts/seed_yield_partners.py
```

This seeds ~30 partners across categories:
- Medical (Dental, General, Beauty)
- Finance (Insurance, Mortgage, Banking)
- Legal
- Real Estate
- Travel
- Automotive
- Jobs
- Education
- Technology/Hosting
- Shopping
- Food/Delivery

### 3. Configure DNS

For yield domains to work, you need to set up DNS infrastructure:

#### Option A: Dedicated Nameservers (Recommended for Scale)

1. Set up two nameserver instances (e.g., `ns1.pounce.ch`, `ns2.pounce.ch`)
2. Run PowerDNS or similar with a backend that queries your yield_domains table
3. Return A records pointing to your yield routing service

#### Option B: CNAME Approach (Simpler)

1. Set up a wildcard SSL certificate for `*.yield.pounce.ch`
2. Configure Nginx/Caddy to handle all incoming hosts
3. Users add CNAME: `@ → yield.pounce.ch`

### 4. Nginx Configuration

For host-based routing, add this to your nginx config:

```nginx
# Yield domain catch-all
server {
    listen 443 ssl http2;
    server_name ~^(?<domain>.+)$;
    
    # Wildcard cert
    ssl_certificate /etc/ssl/yield.pounce.ch.crt;
    ssl_certificate_key /etc/ssl/yield.pounce.ch.key;
    
    location / {
        proxy_pass http://backend:8000/api/v1/r/$domain;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
```

### 5. Partner Integration

Each affiliate partner requires:

1. **Tracking URL Template**: How to pass click IDs to the partner
2. **Webhook URL**: Where the partner sends conversion data back

Update partners in the database or via admin panel:

```sql
UPDATE affiliate_partners 
SET tracking_url_template = 'https://partner.com/?clickid={click_id}&ref={domain}'
WHERE slug = 'partner_slug';
```

### 6. Webhook Configuration

Partners send conversion data to:

```
POST https://api.pounce.ch/api/v1/yield-webhooks/{partner_slug}

{
  "event_type": "lead",
  "domain": "zahnarzt-zuerich.ch",
  "transaction_id": "abc123",
  "amount": 25.00,
  "currency": "CHF"
}
```

For Awin network, use the dedicated endpoint:
```
POST https://api.pounce.ch/api/v1/yield-webhooks/awin/postback
```

## API Endpoints

### Public

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/yield/analyze?domain=X` | Analyze domain intent (no auth) |
| GET | `/api/v1/yield/partners` | List available partners |

### Authenticated (User)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/yield/dashboard` | User yield dashboard |
| GET | `/api/v1/yield/domains` | List user's yield domains |
| POST | `/api/v1/yield/activate` | Activate a domain |
| POST | `/api/v1/yield/domains/{id}/verify` | Verify DNS setup |
| GET | `/api/v1/yield/transactions` | Transaction history |
| GET | `/api/v1/yield/payouts` | Payout history |

### Routing

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/r/{domain}` | Route traffic & track click |
| GET | `/api/v1/r/{domain}?direct=true` | Direct redirect (no landing) |

### Webhooks (Partner → Pounce)

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/yield-webhooks/{partner}` | Generic partner webhook |
| POST | `/api/v1/yield-webhooks/awin/postback` | Awin network postback |
| POST | `/api/v1/yield-webhooks/confirm/{tx_id}` | Manual confirmation (internal) |
| POST | `/api/v1/yield-webhooks/batch-import` | Bulk import (internal) |

## Revenue Model

- **Clicks**: Usually CPC (cost per click), CHF 0.10-0.60
- **Leads**: CPL (cost per lead), CHF 15-120
- **Sales**: CPS (cost per sale), 2-10% of sale value

Revenue split:
- **User**: 70%
- **Pounce**: 30%

## Intent Categories

The IntentDetector recognizes these categories:

| Category | Subcategories | Example Domains |
|----------|---------------|-----------------|
| medical | dental, general, beauty | zahnarzt.ch, arzt-bern.ch |
| finance | insurance, mortgage, banking | versicherung.ch, hypothek.ch |
| legal | general | anwalt-zuerich.ch |
| realestate | buy, rent | wohnung-mieten.ch |
| travel | flights, hotels | flug-buchen.ch |
| auto | buy, service | autokauf.ch |
| jobs | - | stellenmarkt.ch |
| education | - | kurse-online.ch |
| tech | hosting, software | webhosting.ch |
| shopping | general, fashion | mode-shop.ch |
| food | restaurant, delivery | pizza-lieferung.ch |

## Monitoring

### Metrics

Enable Prometheus metrics:

```env
ENABLE_METRICS=true
```

Key yield metrics:
- `yield_clicks_total{domain, partner}`
- `yield_conversions_total{domain, partner, type}`
- `yield_revenue_total{currency}`

### Alerts

Set up alerts for:
- Webhook failures
- Low conversion rates
- DNS verification failures
- Partner API errors

## Troubleshooting

### Domain not routing

1. Check DNS: `dig +short {domain}`
2. Verify domain status: `SELECT status FROM yield_domains WHERE domain = '{domain}'`
3. Check nginx logs for routing errors

### No conversions

1. Verify partner webhook URL is correct
2. Check webhook logs for incoming calls
3. Validate transaction ID format

### Low revenue

1. Check intent detection: Some domains may be classified as "generic"
2. Review partner matching: Higher-priority partners should be assigned
3. Analyze geo distribution: Swiss visitors convert better

## Security Considerations

- All partner webhooks should use HMAC signature verification
- IP addresses are hashed before storage (privacy)
- User revenue data is isolated by user_id
- Rate limiting on routing endpoint

## Support

For issues with:
- Partner integrations: partners@pounce.ch
- Technical issues: dev@pounce.ch
- Payout questions: finance@pounce.ch

